* [Qemu-devel] expose host CPU features to guests @ 2007-09-05 17:45 danken 2007-09-05 19:26 ` [Qemu-devel] Re: [kvm-devel] " Anthony Liguori 2007-09-10 7:40 ` [Qemu-devel] expose host CPU features to guests: Take 2 Dan Kenigsberg 0 siblings, 2 replies; 43+ messages in thread From: danken @ 2007-09-05 17:45 UTC (permalink / raw) To: qemu-devel, kvm-devel Hi, It's a pity not to use a host CPU feature if it is available. This patch exposes host CPU features to guests. It allows fine-tuning the presented features from the command-line. The code could use some serious clean ups, but I think it is interesting enough right now. I'd be happy to hear your opinion and suggestions. The diff are done against qemu cvs. I tried it with kvm, but I thinkg it should be useful also for kqemu. Regards, Dan. Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.336 diff -u -p -r1.336 vl.c --- vl.c 28 Aug 2007 22:21:40 -0000 1.336 +++ vl.c 5 Sep 2007 15:48:10 -0000 @@ -6575,12 +6575,24 @@ int qemu_register_machine(QEMUMachine *m return 0; } +const char *machine_flavor = 0; + QEMUMachine *find_machine(const char *name) { QEMUMachine *m; + int n; + machine_flavor = strchr(name, ','); + if (machine_flavor) { + n = machine_flavor - name; + machine_flavor++; + } else { + n = strlen(name); + machine_flavor = ""; + } + for(m = first_machine; m != NULL; m = m->next) { - if (!strcmp(m->name, name)) + if (!strncmp(m->name, name, n)) return m; } return NULL; @@ -7343,6 +7355,7 @@ static void read_passwords(void) void register_machines(void) { #if defined(TARGET_I386) + qemu_register_machine(&host_pc_machine); qemu_register_machine(&pc_machine); qemu_register_machine(&isapc_machine); #elif defined(TARGET_PPC) Index: vl.h =================================================================== RCS file: /sources/qemu/qemu/vl.h,v retrieving revision 1.264 diff -u -p -r1.264 vl.h --- vl.h 26 Aug 2007 17:46:00 -0000 1.264 +++ vl.h 5 Sep 2007 15:48:10 -0000 @@ -1156,6 +1156,7 @@ void piix4_smbus_register_device(SMBusDe void acpi_bios_init(void); /* pc.c */ +extern QEMUMachine host_pc_machine; extern QEMUMachine pc_machine; extern QEMUMachine isapc_machine; extern int fd_bootchk; Index: hw/pc.c =================================================================== RCS file: /sources/qemu/qemu/hw/pc.c,v retrieving revision 1.83 diff -u -p -r1.83 pc.c --- hw/pc.c 26 Aug 2007 17:51:39 -0000 1.83 +++ hw/pc.c 5 Sep 2007 15:48:10 -0000 @@ -965,6 +965,28 @@ static void pc_init_isa(int ram_size, in initrd_filename, 0); } +int use_hostlike_cpu = 0; + +static void pc_init_hostlike(ram_addr_t ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, + int snapshot, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename) +{ + use_hostlike_cpu = 1; + pc_init1(ram_size, vga_ram_size, boot_device, + ds, fd_filename, snapshot, + kernel_filename, kernel_cmdline, + initrd_filename, 1); +} + +QEMUMachine host_pc_machine = { + "host", + "Standard PC with host-like CPU", + pc_init_hostlike, +}; + QEMUMachine pc_machine = { "pc", "Standard PC", Index: target-i386/cpu.h =================================================================== RCS file: /sources/qemu/qemu/target-i386/cpu.h,v retrieving revision 1.45 diff -u -p -r1.45 cpu.h --- target-i386/cpu.h 11 Jul 2007 22:48:58 -0000 1.45 +++ target-i386/cpu.h 5 Sep 2007 15:48:10 -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 -p -r1.48 helper2.c --- target-i386/helper2.c 31 Jul 2007 23:09:18 -0000 1.48 +++ target-i386/helper2.c 5 Sep 2007 15:48:10 -0000 @@ -45,6 +45,272 @@ int modify_ldt(int func, void *ptr, unsi #endif #endif /* USE_CODE_COPY */ +/* 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); +} + +static void apply_machine_flavor(CPUX86State *env) +{ + 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; + + extern char *machine_flavor; + char *s = strdup(machine_flavor); + char *featurestr = strtok(s, ","); + + 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; +} + +static int read_one_cpu_info(CPUX86State *env, FILE *f) +{ + char line[300], *val; + char vendor_id[13]; + int family = -1, model = -1, stepping = -1; + int features = 0, ext_features = 0, ext2_features = 0; + + while (fgets(line, sizeof(line), f)) { + if (!strtok(line, "\t") || line[0]=='\n') { + break; + } + val = strtok(NULL, "\t:"); + if (!val) + val = ""; + if (*val==' ') + val++; + + if (!strcmp(line,"vendor_id")) { + strncpy(vendor_id, val, sizeof(vendor_id) - 1); + vendor_id[sizeof(vendor_id)-1] = 0; + } + if (!strcmp(line,"cpu family")) { + family = atoi(val); + } + if (!strcmp(line,"model")) { + model = atoi(val); + } + if (!strcmp(line,"stepping")) { + stepping = atoi(val); + } + if (!strcmp(line,"flags")) { + char *flagname; + struct flagstorage { + char *name; + int bit; + int *container; + }; + + flagname = strtok(val, " "); + while (flagname) { + add_flagname_to_bitmaps(flagname, &features, &ext_features, &ext2_features); + flagname = strtok(NULL, " \n"); + } + features &= ~CPUID_ACPI; /* acpi causes guest kernel panic on boot time, in cpu_identify */ + ext_features &= ~CPUID_EXT_VMX; /* KVM is not recursive */ + } + } + if (family==-1 || model==-1 || stepping==-1) + return -1; + env->cpuid_level = 2; + env->cpuid_vendor1 = *(uint32_t *)&vendor_id[0]; + env->cpuid_vendor2 = *(uint32_t *)&vendor_id[4]; + env->cpuid_vendor3 = *(uint32_t *)&vendor_id[8]; + env->cpuid_version = (family << 8) | (model << 4) | stepping; + env->cpuid_features = features; + env->cpuid_ext_features = ext_features; + env->cpuid_ext2_features = ext2_features; + env->pat = 0x0007040600070406ULL; + /* TODO expose real cpuid extended level */ +#ifdef TARGET_X86_64 + env->cpuid_xlevel = 0x80000008; +#else + env->cpuid_xlevel = 0; +#endif + return 0; +} + +static int set_guest_cpu_hostlike(CPUX86State *env) { + FILE *f; + f = fopen("/proc/cpuinfo", "r"); + if (!f) { + fprintf(stderr, "falling back to standard guest cpu\n"); + return -1; + } + read_one_cpu_info(env, f); + fclose(f); + return 0; +} + +static int set_guest_cpu_standard(CPUX86State *env) +{ + int family, model, stepping; +#ifdef TARGET_X86_64 + env->cpuid_vendor1 = 0x68747541; /* "Auth" */ + env->cpuid_vendor2 = 0x69746e65; /* "enti" */ + env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ + family = 6; + model = 2; + stepping = 3; +#else + env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ + env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ + env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ +#if 0 + /* pentium 75-200 */ + family = 5; + model = 2; + stepping = 11; +#else + /* pentium pro */ + family = 6; + model = 3; + stepping = 3; +#endif +#endif + env->cpuid_level = 2; + env->cpuid_version = (family << 8) | (model << 4) | stepping; + env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | + CPUID_TSC | CPUID_MSR | CPUID_MCE | + CPUID_CX8 | CPUID_PGE | CPUID_CMOV | + CPUID_PAT); + env->pat = 0x0007040600070406ULL; + 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; +#ifdef TARGET_X86_64 + /* currently not enabled for std i386 because not fully tested */ + env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); + env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; + env->cpuid_xlevel = 0x80000008; + + /* these features are needed for Win64 and aren't fully implemented */ + env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; + /* this feature is needed for Solaris and isn't fully implemented */ + env->cpuid_features |= CPUID_PSE36; +#endif + return 0; +} + CPUX86State *cpu_x86_init(void) { CPUX86State *env; @@ -80,64 +346,23 @@ CPUX86State *cpu_x86_init(void) } #endif { - int family, model, stepping; -#ifdef TARGET_X86_64 - env->cpuid_vendor1 = 0x68747541; /* "Auth" */ - env->cpuid_vendor2 = 0x69746e65; /* "enti" */ - env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ - family = 6; - model = 2; - stepping = 3; -#else - env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ - env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ - env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ -#if 0 - /* pentium 75-200 */ - family = 5; - model = 2; - stepping = 11; -#else - /* pentium pro */ - family = 6; - model = 3; - stepping = 3; -#endif -#endif - env->cpuid_level = 2; - env->cpuid_version = (family << 8) | (model << 4) | stepping; - env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | - CPUID_TSC | CPUID_MSR | CPUID_MCE | - CPUID_CX8 | CPUID_PGE | CPUID_CMOV | - CPUID_PAT); - env->pat = 0x0007040600070406ULL; - 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)); - } + extern int use_hostlike_cpu; + if (!use_hostlike_cpu || set_guest_cpu_hostlike(env)) + set_guest_cpu_standard(env); + apply_machine_flavor(env); + } + { + 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)); } -#ifdef TARGET_X86_64 - /* currently not enabled for std i386 because not fully tested */ - env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); - env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; - env->cpuid_xlevel = 0x80000008; - - /* these features are needed for Win64 and aren't fully implemented */ - env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; - /* this feature is needed for Solaris and isn't fully implemented */ - env->cpuid_features |= CPUID_PSE36; -#endif } cpu_reset(env); #ifdef USE_KQEMU ^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] Re: [kvm-devel] expose host CPU features to guests 2007-09-05 17:45 [Qemu-devel] expose host CPU features to guests danken @ 2007-09-05 19:26 ` Anthony Liguori 2007-09-05 19:34 ` Avi Kivity 2007-09-07 10:47 ` Jamie Lokier 2007-09-10 7:40 ` [Qemu-devel] expose host CPU features to guests: Take 2 Dan Kenigsberg 1 sibling, 2 replies; 43+ messages in thread From: Anthony Liguori @ 2007-09-05 19:26 UTC (permalink / raw) To: danken; +Cc: kvm-devel, qemu-devel On Wed, 2007-09-05 at 20:45 +0300, danken@qumranet.com wrote: > Hi, > > It's a pity not to use a host CPU feature if it is available. This patch > exposes host CPU features to guests. It allows fine-tuning the presented > features from the command-line. > > The code could use some serious clean ups, but I think it is interesting > enough right now. I'd be happy to hear your opinion and suggestions. > The diff are done against qemu cvs. I tried it with kvm, but I thinkg it > should be useful also for kqemu. I like this idea but I have some suggestions about the general approach. I think instead of defining another machine type, it would be better to just have a command line option like -cpuid that took a comma separate string of features with "all" meaning all features that the host has. I also think it would be nicer to use cpuid() directly instead of attempting to parse /proc/cpuinfo. Regards, Anthony Liguori > Regards, > > Dan. > > Index: vl.c > =================================================================== > RCS file: /sources/qemu/qemu/vl.c,v > retrieving revision 1.336 > diff -u -p -r1.336 vl.c > --- vl.c 28 Aug 2007 22:21:40 -0000 1.336 > +++ vl.c 5 Sep 2007 15:48:10 -0000 > @@ -6575,12 +6575,24 @@ int qemu_register_machine(QEMUMachine *m > return 0; > } > > +const char *machine_flavor = 0; > + > QEMUMachine *find_machine(const char *name) > { > QEMUMachine *m; > > + int n; > + machine_flavor = strchr(name, ','); > + if (machine_flavor) { > + n = machine_flavor - name; > + machine_flavor++; > + } else { > + n = strlen(name); > + machine_flavor = ""; > + } > + > for(m = first_machine; m != NULL; m = m->next) { > - if (!strcmp(m->name, name)) > + if (!strncmp(m->name, name, n)) > return m; > } > return NULL; > @@ -7343,6 +7355,7 @@ static void read_passwords(void) > void register_machines(void) > { > #if defined(TARGET_I386) > + qemu_register_machine(&host_pc_machine); > qemu_register_machine(&pc_machine); > qemu_register_machine(&isapc_machine); > #elif defined(TARGET_PPC) > Index: vl.h > =================================================================== > RCS file: /sources/qemu/qemu/vl.h,v > retrieving revision 1.264 > diff -u -p -r1.264 vl.h > --- vl.h 26 Aug 2007 17:46:00 -0000 1.264 > +++ vl.h 5 Sep 2007 15:48:10 -0000 > @@ -1156,6 +1156,7 @@ void piix4_smbus_register_device(SMBusDe > void acpi_bios_init(void); > > /* pc.c */ > +extern QEMUMachine host_pc_machine; > extern QEMUMachine pc_machine; > extern QEMUMachine isapc_machine; > extern int fd_bootchk; > Index: hw/pc.c > =================================================================== > RCS file: /sources/qemu/qemu/hw/pc.c,v > retrieving revision 1.83 > diff -u -p -r1.83 pc.c > --- hw/pc.c 26 Aug 2007 17:51:39 -0000 1.83 > +++ hw/pc.c 5 Sep 2007 15:48:10 -0000 > @@ -965,6 +965,28 @@ static void pc_init_isa(int ram_size, in > initrd_filename, 0); > } > > +int use_hostlike_cpu = 0; > + > +static void pc_init_hostlike(ram_addr_t ram_size, int vga_ram_size, int boot_device, > + DisplayState *ds, const char **fd_filename, > + int snapshot, > + const char *kernel_filename, > + const char *kernel_cmdline, > + const char *initrd_filename) > +{ > + use_hostlike_cpu = 1; > + pc_init1(ram_size, vga_ram_size, boot_device, > + ds, fd_filename, snapshot, > + kernel_filename, kernel_cmdline, > + initrd_filename, 1); > +} > + > +QEMUMachine host_pc_machine = { > + "host", > + "Standard PC with host-like CPU", > + pc_init_hostlike, > +}; > + > QEMUMachine pc_machine = { > "pc", > "Standard PC", > Index: target-i386/cpu.h > =================================================================== > RCS file: /sources/qemu/qemu/target-i386/cpu.h,v > retrieving revision 1.45 > diff -u -p -r1.45 cpu.h > --- target-i386/cpu.h 11 Jul 2007 22:48:58 -0000 1.45 > +++ target-i386/cpu.h 5 Sep 2007 15:48:10 -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 -p -r1.48 helper2.c > --- target-i386/helper2.c 31 Jul 2007 23:09:18 -0000 1.48 > +++ target-i386/helper2.c 5 Sep 2007 15:48:10 -0000 > @@ -45,6 +45,272 @@ int modify_ldt(int func, void *ptr, unsi > #endif > #endif /* USE_CODE_COPY */ > > +/* 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); > +} > + > +static void apply_machine_flavor(CPUX86State *env) > +{ > + 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; > + > + extern char *machine_flavor; > + char *s = strdup(machine_flavor); > + char *featurestr = strtok(s, ","); > + > + 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; > +} > + > +static int read_one_cpu_info(CPUX86State *env, FILE *f) > +{ > + char line[300], *val; > + char vendor_id[13]; > + int family = -1, model = -1, stepping = -1; > + int features = 0, ext_features = 0, ext2_features = 0; > + > + while (fgets(line, sizeof(line), f)) { > + if (!strtok(line, "\t") || line[0]=='\n') { > + break; > + } > + val = strtok(NULL, "\t:"); > + if (!val) > + val = ""; > + if (*val==' ') > + val++; > + > + if (!strcmp(line,"vendor_id")) { > + strncpy(vendor_id, val, sizeof(vendor_id) - 1); > + vendor_id[sizeof(vendor_id)-1] = 0; > + } > + if (!strcmp(line,"cpu family")) { > + family = atoi(val); > + } > + if (!strcmp(line,"model")) { > + model = atoi(val); > + } > + if (!strcmp(line,"stepping")) { > + stepping = atoi(val); > + } > + if (!strcmp(line,"flags")) { > + char *flagname; > + struct flagstorage { > + char *name; > + int bit; > + int *container; > + }; > + > + flagname = strtok(val, " "); > + while (flagname) { > + add_flagname_to_bitmaps(flagname, &features, &ext_features, &ext2_features); > + flagname = strtok(NULL, " \n"); > + } > + features &= ~CPUID_ACPI; /* acpi causes guest kernel panic on boot time, in cpu_identify */ > + ext_features &= ~CPUID_EXT_VMX; /* KVM is not recursive */ > + } > + } > + if (family==-1 || model==-1 || stepping==-1) > + return -1; > + env->cpuid_level = 2; > + env->cpuid_vendor1 = *(uint32_t *)&vendor_id[0]; > + env->cpuid_vendor2 = *(uint32_t *)&vendor_id[4]; > + env->cpuid_vendor3 = *(uint32_t *)&vendor_id[8]; > + env->cpuid_version = (family << 8) | (model << 4) | stepping; > + env->cpuid_features = features; > + env->cpuid_ext_features = ext_features; > + env->cpuid_ext2_features = ext2_features; > + env->pat = 0x0007040600070406ULL; > + /* TODO expose real cpuid extended level */ > +#ifdef TARGET_X86_64 > + env->cpuid_xlevel = 0x80000008; > +#else > + env->cpuid_xlevel = 0; > +#endif > + return 0; > +} > + > +static int set_guest_cpu_hostlike(CPUX86State *env) { > + FILE *f; > + f = fopen("/proc/cpuinfo", "r"); > + if (!f) { > + fprintf(stderr, "falling back to standard guest cpu\n"); > + return -1; > + } > + read_one_cpu_info(env, f); > + fclose(f); > + return 0; > +} > + > +static int set_guest_cpu_standard(CPUX86State *env) > +{ > + int family, model, stepping; > +#ifdef TARGET_X86_64 > + env->cpuid_vendor1 = 0x68747541; /* "Auth" */ > + env->cpuid_vendor2 = 0x69746e65; /* "enti" */ > + env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ > + family = 6; > + model = 2; > + stepping = 3; > +#else > + env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ > + env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ > + env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ > +#if 0 > + /* pentium 75-200 */ > + family = 5; > + model = 2; > + stepping = 11; > +#else > + /* pentium pro */ > + family = 6; > + model = 3; > + stepping = 3; > +#endif > +#endif > + env->cpuid_level = 2; > + env->cpuid_version = (family << 8) | (model << 4) | stepping; > + env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | > + CPUID_TSC | CPUID_MSR | CPUID_MCE | > + CPUID_CX8 | CPUID_PGE | CPUID_CMOV | > + CPUID_PAT); > + env->pat = 0x0007040600070406ULL; > + 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; > +#ifdef TARGET_X86_64 > + /* currently not enabled for std i386 because not fully tested */ > + env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); > + env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; > + env->cpuid_xlevel = 0x80000008; > + > + /* these features are needed for Win64 and aren't fully implemented */ > + env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; > + /* this feature is needed for Solaris and isn't fully implemented */ > + env->cpuid_features |= CPUID_PSE36; > +#endif > + return 0; > +} > + > CPUX86State *cpu_x86_init(void) > { > CPUX86State *env; > @@ -80,64 +346,23 @@ CPUX86State *cpu_x86_init(void) > } > #endif > { > - int family, model, stepping; > -#ifdef TARGET_X86_64 > - env->cpuid_vendor1 = 0x68747541; /* "Auth" */ > - env->cpuid_vendor2 = 0x69746e65; /* "enti" */ > - env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ > - family = 6; > - model = 2; > - stepping = 3; > -#else > - env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ > - env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ > - env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ > -#if 0 > - /* pentium 75-200 */ > - family = 5; > - model = 2; > - stepping = 11; > -#else > - /* pentium pro */ > - family = 6; > - model = 3; > - stepping = 3; > -#endif > -#endif > - env->cpuid_level = 2; > - env->cpuid_version = (family << 8) | (model << 4) | stepping; > - env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | > - CPUID_TSC | CPUID_MSR | CPUID_MCE | > - CPUID_CX8 | CPUID_PGE | CPUID_CMOV | > - CPUID_PAT); > - env->pat = 0x0007040600070406ULL; > - 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)); > - } > + extern int use_hostlike_cpu; > + if (!use_hostlike_cpu || set_guest_cpu_hostlike(env)) > + set_guest_cpu_standard(env); > + apply_machine_flavor(env); > + } > + { > + 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)); > } > -#ifdef TARGET_X86_64 > - /* currently not enabled for std i386 because not fully tested */ > - env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); > - env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; > - env->cpuid_xlevel = 0x80000008; > - > - /* these features are needed for Win64 and aren't fully implemented */ > - env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; > - /* this feature is needed for Solaris and isn't fully implemented */ > - env->cpuid_features |= CPUID_PSE36; > -#endif > } > cpu_reset(env); > #ifdef USE_KQEMU > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > _______________________________________________ > kvm-devel mailing list > kvm-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/kvm-devel ^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] Re: [kvm-devel] expose host CPU features to guests 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-07 10:47 ` Jamie Lokier 1 sibling, 1 reply; 43+ messages in thread From: Avi Kivity @ 2007-09-05 19:34 UTC (permalink / raw) To: Anthony Liguori; +Cc: danken, kvm-devel, qemu-devel Anthony Liguori wrote: > On Wed, 2007-09-05 at 20:45 +0300, danken@qumranet.com wrote: > >> Hi, >> >> It's a pity not to use a host CPU feature if it is available. This patch >> exposes host CPU features to guests. It allows fine-tuning the presented >> features from the command-line. >> >> The code could use some serious clean ups, but I think it is interesting >> enough right now. I'd be happy to hear your opinion and suggestions. >> The diff are done against qemu cvs. I tried it with kvm, but I thinkg it >> should be useful also for kqemu. >> > > I like this idea but I have some suggestions about the general approach. > I think instead of defining another machine type, it would be better to > just have a command line option like -cpuid that took a comma separate > string of features with "all" meaning all features that the host has. > > I think qemu-cvs has a -cpu option for non-x86 which could be used for this. Agree machine types are the wrong approach. > I also think it would be nicer to use cpuid() directly instead of > attempting to parse /proc/cpuinfo. > Yes. -- Any sufficiently difficult bug is indistinguishable from a feature. ^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] Re: [kvm-devel] expose host CPU features to guests 2007-09-05 19:34 ` Avi Kivity @ 2007-09-05 19:44 ` Daniel P. Berrange 2007-09-06 0:30 ` Paul Brook 0 siblings, 1 reply; 43+ messages in thread From: Daniel P. Berrange @ 2007-09-05 19:44 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel, qemu-devel On Wed, Sep 05, 2007 at 10:34:45PM +0300, Avi Kivity wrote: > Anthony Liguori wrote: > > On Wed, 2007-09-05 at 20:45 +0300, danken@qumranet.com wrote: > > > >> Hi, > >> > >> It's a pity not to use a host CPU feature if it is available. This patch > >> exposes host CPU features to guests. It allows fine-tuning the presented > >> features from the command-line. > >> > >> The code could use some serious clean ups, but I think it is interesting > >> enough right now. I'd be happy to hear your opinion and suggestions. > >> The diff are done against qemu cvs. I tried it with kvm, but I thinkg it > >> should be useful also for kqemu. > >> > > > > I like this idea but I have some suggestions about the general approach. > > I think instead of defining another machine type, it would be better to > > just have a command line option like -cpuid that took a comma separate > > string of features with "all" meaning all features that the host has. > > > > > > I think qemu-cvs has a -cpu option for non-x86 which could be used for > this. Agree machine types are the wrong approach. Yep, machine types are already used to switch between a different concept so using the new -cpu option would make sense. Could perhaps extend the syntax so that instead of '-cpu TYPE' it used '-cpu TYPE,FEATURES' where FEATURES was an optional list of CPU features to allow - though perhaps with some shortcut for specifying 'match the host cpu type & features'. Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=| ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] Re: [kvm-devel] expose host CPU features to guests 2007-09-05 19:44 ` Daniel P. Berrange @ 2007-09-06 0:30 ` Paul Brook 2007-09-06 8:46 ` Avi Kivity 0 siblings, 1 reply; 43+ messages in thread From: Paul Brook @ 2007-09-06 0:30 UTC (permalink / raw) To: qemu-devel, Daniel P. Berrange; +Cc: kvm-devel > > I think qemu-cvs has a -cpu option for non-x86 which could be used for > > this. Agree machine types are the wrong approach. > > Yep, machine types are already used to switch between a different concept > so using the new -cpu option would make sense. Could perhaps extend the > syntax so that instead of '-cpu TYPE' it used '-cpu TYPE,FEATURES' where > FEATURES was an optional list of CPU features to allow I tried this for ARM, and having separate type+features isn't worth the effort. The internal implementation is feature based, but IMHO there's little benefit exposing that to the user. Just define appropriate CPUs for the interesting feature combinations. Of course the x86 emulation doesn't currently support restricting the architecture features available. To make the --cpu option useful you need to implement that first. Paul ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] Re: [kvm-devel] expose host CPU features to guests 2007-09-06 0:30 ` Paul Brook @ 2007-09-06 8:46 ` Avi Kivity 0 siblings, 0 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-06 8:46 UTC (permalink / raw) To: Paul Brook; +Cc: kvm-devel, qemu-devel Paul Brook wrote: >>> I think qemu-cvs has a -cpu option for non-x86 which could be used for >>> this. Agree machine types are the wrong approach. >>> >> Yep, machine types are already used to switch between a different concept >> so using the new -cpu option would make sense. Could perhaps extend the >> syntax so that instead of '-cpu TYPE' it used '-cpu TYPE,FEATURES' where >> FEATURES was an optional list of CPU features to allow >> > > I tried this for ARM, and having separate type+features isn't worth the > effort. The internal implementation is feature based, but IMHO there's little > benefit exposing that to the user. Just define appropriate CPUs for the > interesting feature combinations. > > The use case is different. We don't care about the actual features, but about finding the greatest common denominator in a virtualization farm. I don't see this as useful for qemu; rather kvm and kqemu. > Of course the x86 emulation doesn't currently support restricting the > architecture features available. To make the --cpu option useful you need to > implement that first. > Applications will not use a feature that is not present in cpuid, so that is not an issue. For the virtualization use case, it is also impossible to turn off support for a feature. -- Any sufficiently difficult bug is indistinguishable from a feature. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] Re: [kvm-devel] expose host CPU features to guests 2007-09-05 19:26 ` [Qemu-devel] Re: [kvm-devel] " Anthony Liguori 2007-09-05 19:34 ` Avi Kivity @ 2007-09-07 10:47 ` Jamie Lokier 2007-09-09 7:51 ` [kvm-devel] [Qemu-devel] " Avi Kivity 1 sibling, 1 reply; 43+ messages in thread From: Jamie Lokier @ 2007-09-07 10:47 UTC (permalink / raw) To: qemu-devel; +Cc: danken, kvm-devel Anthony Liguori wrote: > I like this idea but I have some suggestions about the general approach. > I think instead of defining another machine type, it would be better to > just have a command line option like -cpuid that took a comma separate > string of features with "all" meaning all features that the host has. I like the idea of a flag to enable specific features, but I think "host" would be a better name for the features of the host. "all" seems more appropriate to enable all the features the emulator can support, which can include features which the host does not support itself. If it's a comma separated list, it would be good to be able to write something like this example, which selects all the host features but then overrides it by disabling the psn feature: -cpuid host,-psn Is it intended that these flags will also control the actual features which Qemu allows or emulates, or only what cpuid reports to the guest? > I also think it would be nicer to use cpuid() directly instead of > attempting to parse /proc/cpuinfo. Occasionally the features in /proc/cpuinfo differ from what the cpuid instruction reports. They are CPU bug workarounds (features disabled intentionally even though cpuid reports them), CPU features which aren't properly reported (enabled intentionally in cpuinfo), and boot flag requests (features disabled due to request from the boot command line). I'm inclined to think the feature list in /proc/cpuinfo is more appropriate, for choosing the best set of host features to make available to guests. It's unlikely that Qemu itself will duplicate the logic of known workarounds for specific, obscure, buggy host CPUs. There is also /dev/cpu/%d/cpuinfo (for %d = 0, 1, etc.) on some Linux distros, I think. -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 2007-09-07 10:47 ` Jamie Lokier @ 2007-09-09 7:51 ` Avi Kivity 2007-09-09 12:47 ` Jamie Lokier 0 siblings, 1 reply; 43+ messages in thread From: Avi Kivity @ 2007-09-09 7:51 UTC (permalink / raw) To: Jamie Lokier; +Cc: kvm-devel, qemu-devel Jamie Lokier wrote: > Anthony Liguori wrote: > >> I like this idea but I have some suggestions about the general approach. >> I think instead of defining another machine type, it would be better to >> just have a command line option like -cpuid that took a comma separate >> string of features with "all" meaning all features that the host has. >> > > I like the idea of a flag to enable specific features, but I think > "host" would be a better name for the features of the host. > > "all" seems more appropriate to enable all the features the emulator > can support, which can include features which the host does not > support itself. > > If it's a comma separated list, it would be good to be able to write > something like this example, which selects all the host features but > then overrides it by disabling the psn feature: > > -cpuid host,-psn > Yes, 'host' and 'all' make more sense the way you describe them from the emulator perspective. > Is it intended that these flags will also control the actual features > which Qemu allows or emulates, or only what cpuid reports to the guest? > > The cpuid features are sufficient (and there's precedent -- some mobile intel processors support pae but don't report it). >> I also think it would be nicer to use cpuid() directly instead of >> attempting to parse /proc/cpuinfo. >> > > Occasionally the features in /proc/cpuinfo differ from what the cpuid > instruction reports. They are CPU bug workarounds (features disabled > intentionally even though cpuid reports them), CPU features which > aren't properly reported (enabled intentionally in cpuinfo), and boot > flag requests (features disabled due to request from the boot command > line). > > I'm inclined to think the feature list in /proc/cpuinfo is more > appropriate, for choosing the best set of host features to make > available to guests. It's unlikely that Qemu itself will duplicate > the logic of known workarounds for specific, obscure, buggy host CPUs. > > There is also /dev/cpu/%d/cpuinfo (for %d = 0, 1, etc.) on some Linux > distros, I think. > Well, the guest will invoke its own workaround logic to disable buggy features, so I see no issue here. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 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 0 siblings, 1 reply; 43+ messages in thread From: Jamie Lokier @ 2007-09-09 12:47 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel, qemu-devel Avi Kivity wrote: > Well, the guest will invoke its own workaround logic to disable buggy > features, so I see no issue here. The guest can only do this if it has exactly the correct id information for the host processor (e.g. "This is an Intel Pentium Pro model XXX"), not just the list of safe to use CPU features. This isn't possible in a virtualisation cluster of many different CPUs where the point is to advertise the common set of cpuid features, and for the guest images to be able to migrate between different CPUs in the cluster. Then, the common cpuid features must be found by combining the /proc/cpuinfo from each node in the cluster. But I guess that's separate from the part of Qemu we are discussing; it would be done by another program, preparing the -cpuid argument. But sometimes it's good to run a simple guest (e.g. someone's pet OS project, or anything written for Intel only which was more common in the past) which doesn't have all the detailed obscure workarounds of something like Linux, but still be able to take advantage of the workarounds and obscure knowledge in the host. The alternative is Qemu itself may end up having to have some of these obscure workarounds :/ For example, the sysenter instruction is advertised on early Pentium Pros, but it doesn't work. Linux removes it from the features in /proc/cpuinfo, and doesn't use it. But some guests simply don't get that obscure, and use it if cpuid advertises it. Of course, they don't work on a _real_ early Pentium Pro. But it would be nice if they did work without anything special when run in Qemu on such a host. That's an old chip which I happen to know about, but I'm sure there are more modern similar issues. Perhaps there could be two options then: "-cpuid host-os", and "-cpuid host-cpuid". I would suggest making "host" an alias for "host-os", but I wouldn't object if it were an alias for "host-cpuid" or didn't exist at all, so you had to choose one. -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 2007-09-09 12:47 ` Jamie Lokier @ 2007-09-09 12:55 ` Avi Kivity 2007-09-09 13:07 ` Jamie Lokier 0 siblings, 1 reply; 43+ messages in thread From: Avi Kivity @ 2007-09-09 12:55 UTC (permalink / raw) To: Jamie Lokier; +Cc: kvm-devel, qemu-devel Jamie Lokier wrote: > Avi Kivity wrote: > >> Well, the guest will invoke its own workaround logic to disable buggy >> features, so I see no issue here. >> > > The guest can only do this if it has exactly the correct id > information for the host processor (e.g. "This is an Intel Pentium Pro > model XXX"), not just the list of safe to use CPU features. > > This isn't possible in a virtualisation cluster of many different CPUs > where the point is to advertise the common set of cpuid features, and > for the guest images to be able to migrate between different CPUs in > the cluster. > Well, for a cluster the management software will coordinate all cpuid features, perhaps taking into account features removed by the host kernel. "-cpu host" is for the gentoo user who wants to enable all the nice cpu flags. > Then, the common cpuid features must be found by combining the > /proc/cpuinfo from each node in the cluster. But I guess that's > separate from the part of Qemu we are discussing; it would be done by > another program, preparing the -cpuid argument. > Exactly. > But sometimes it's good to run a simple guest (e.g. someone's pet OS > project, or anything written for Intel only which was more common in > the past) which doesn't have all the detailed obscure workarounds of > something like Linux, but still be able to take advantage of the > workarounds and obscure knowledge in the host. > > The alternative is Qemu itself may end up having to have some of these > obscure workarounds :/ > > For example, the sysenter instruction is advertised on early Pentium > Pros, but it doesn't work. Linux removes it from the features in > /proc/cpuinfo, and doesn't use it. But some guests simply don't get > that obscure, and use it if cpuid advertises it. Of course, they > don't work on a _real_ early Pentium Pro. But it would be nice if > they did work without anything special when run in Qemu on such a > host. That's an old chip which I happen to know about, but I'm sure > there are more modern similar issues. > > Perhaps there could be two options then: "-cpuid host-os", and "-cpuid > host-cpuid". I would suggest making "host" an alias for "host-os", > but I wouldn't object if it were an alias for "host-cpuid" or didn't > exist at all, so you had to choose one. > Let's start with '-cpu host' as 'cpu host-cpuid' and implement '-cpu host-os' on the first bug report? I have a feeling we won't ever see it. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 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 0 siblings, 2 replies; 43+ messages in thread From: Jamie Lokier @ 2007-09-09 13:07 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel, qemu-devel Avi Kivity wrote: > Let's start with '-cpu host' as 'cpu host-cpuid' and implement '-cpu > host-os' on the first bug report? I have a feeling we won't ever see it. I have a feeling you won't ever see it either, but not because it's a missing feature. Instead, I think a very small number of users will spend hours frustrated that some obscure guest doesn't work properly on their obscure x86 hardware, then they will learn that they should not use "-cpuid host" for that guest on that hardware, even though it works fine with other guests, and then their problem will be solved (albeit at a cost), and seen as such an obscure combination that it might never be reported to Qemu developers. In other words, host-os is what _I'd_ implement because I care too much about the poor obscure users and think it's the safe option, but I'm not doing the implementing here ;-) If you are curious what the differences are, do this in a current Linux source tree: egrep -R '(set|clear)_bit\(X86_FEATURE' arch/{i386,x86_64}/kernel -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 2007-09-09 13:07 ` Jamie Lokier @ 2007-09-09 13:14 ` Avi Kivity 2007-09-09 15:25 ` Paul Brook 1 sibling, 0 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-09 13:14 UTC (permalink / raw) To: Jamie Lokier; +Cc: kvm-devel, qemu-devel Jamie Lokier wrote: > Avi Kivity wrote: > >> Let's start with '-cpu host' as 'cpu host-cpuid' and implement '-cpu >> host-os' on the first bug report? I have a feeling we won't ever see it. >> > > I have a feeling you won't ever see it either, but not because it's a > missing feature. > > Instead, I think a very small number of users will spend hours > frustrated that some obscure guest doesn't work properly on their > obscure x86 hardware, then they will learn that they should not use > "-cpuid host" for that guest on that hardware, even though it works > fine with other guests, and then their problem will be solved (albeit > at a cost), and seen as such an obscure combination that it might > never be reported to Qemu developers. > > In other words, host-os is what _I'd_ implement because I care too > much about the poor obscure users and think it's the safe option, but > I'm not doing the implementing here ;-) > > If you are curious what the differences are, do this in a current > Linux source tree: > > egrep -R '(set|clear)_bit\(X86_FEATURE' arch/{i386,x86_64}/kernel > > Some of these are Linux issues, not host cpu issues (for example, it looks like VMI disables global pages). Some of these issues may not impact the guest and we'd be removing them unnecessarily. Also, kvm doesn't run on obscure hardware (although kqemu does; qemu itself is not a candidate for -cpu host). -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 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 1 sibling, 1 reply; 43+ messages in thread From: Paul Brook @ 2007-09-09 15:25 UTC (permalink / raw) To: qemu-devel; +Cc: kvm-devel On Sunday 09 September 2007, Jamie Lokier wrote: > Avi Kivity wrote: > > Let's start with '-cpu host' as 'cpu host-cpuid' and implement '-cpu > > host-os' on the first bug report? I have a feeling we won't ever see it. > > In other words, host-os is what _I'd_ implement because I care too > much about the poor obscure users and think it's the safe option, but > I'm not doing the implementing here ;-) I agree. If the host OS has disabled a feature, it's a fair bet it's done that for a reason. What you really want to do is ask your virtualization module what features it supports. Paul ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 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 0 siblings, 2 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-09 15:29 UTC (permalink / raw) To: Paul Brook; +Cc: kvm-devel, qemu-devel Paul Brook wrote: > On Sunday 09 September 2007, Jamie Lokier wrote: > >> Avi Kivity wrote: >> >>> Let's start with '-cpu host' as 'cpu host-cpuid' and implement '-cpu >>> host-os' on the first bug report? I have a feeling we won't ever see it. >>> >> In other words, host-os is what _I'd_ implement because I care too >> much about the poor obscure users and think it's the safe option, but >> I'm not doing the implementing here ;-) >> > > I agree. If the host OS has disabled a feature, it's a fair bet it's done that > for a reason. > > The reason may not be relevant to the guest. > What you really want to do is ask your virtualization module what features it > supports. > Yes, that needs to be an additional filter. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 2007-09-09 15:29 ` Avi Kivity @ 2007-09-09 15:47 ` Jamie Lokier 2007-09-09 16:12 ` Paul Brook 1 sibling, 0 replies; 43+ messages in thread From: Jamie Lokier @ 2007-09-09 15:47 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel, Paul Brook, qemu-devel Avi Kivity wrote: > >I agree. If the host OS has disabled a feature, it's a fair bet it's done > >that for a reason. > > The reason may not be relevant to the guest. For most guests the relevant features are those which work correctly and efficiently on the virtual CPU. If the host OS has disabled a feature, most often that's because the feature doesn't work on the specific host CPU model, but not always. It might be emulated well, but probably not efficiently. In some cases, you might want a guest to see features supported by the host CPU which the host OS has disabled, but I imagine those are unusual - it doesn't seem very likely. Can you give an example? They can be enabled explicitly by the -cpuid flag if needed. -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 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 1 sibling, 2 replies; 43+ messages in thread From: Paul Brook @ 2007-09-09 16:12 UTC (permalink / raw) To: qemu-devel; +Cc: kvm-devel > > What you really want to do is ask your virtualization module what > > features it supports. > > Yes, that needs to be an additional filter. I'd have thought that would be the *only* interesting set for autodetection. Paul ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 2007-09-09 16:12 ` Paul Brook @ 2007-09-09 16:38 ` Avi Kivity 2007-09-10 16:53 ` Jamie Lokier 1 sibling, 0 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-09 16:38 UTC (permalink / raw) To: Paul Brook; +Cc: kvm-devel, qemu-devel Paul Brook wrote: >>> What you really want to do is ask your virtualization module what >>> features it supports. >>> >> Yes, that needs to be an additional filter. >> > > I'd have thought that would be the *only* interesting set for autodetection. > > Yes, you're right. It's pointless to issue cpuid in userspace and mask it in the kernel; rather we can issue it in the kernel , mask out unsupported features, and return it to userspace. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] Re: expose host CPU features to guests 2007-09-09 16:12 ` Paul Brook 2007-09-09 16:38 ` Avi Kivity @ 2007-09-10 16:53 ` Jamie Lokier 1 sibling, 0 replies; 43+ messages in thread From: Jamie Lokier @ 2007-09-10 16:53 UTC (permalink / raw) To: qemu-devel; +Cc: kvm-devel Paul Brook wrote: > > > What you really want to do is ask your virtualization module what > > > features it supports. > > > > Yes, that needs to be an additional filter. > > I'd have thought that would be the *only* interesting set for autodetection. If that means the same as the features which are efficient for the guest, then I agree. If there's a difference, I'd have thought you'd normally want the guest to use only those features which work at near-native performance, not those which involve a trap and long path through the virtualisation/emulation, even if they're supported. No example comes to mind, but that seems like the principle to go for, to me. -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] expose host CPU features to guests: Take 2 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-10 7:40 ` Dan Kenigsberg 2007-09-10 11:47 ` Natalia Portillo 2007-09-24 17:41 ` [Qemu-devel] expose host CPU features to guests: Take 3 Dan Kenigsberg 1 sibling, 2 replies; 43+ messages in thread From: Dan Kenigsberg @ 2007-09-10 7:40 UTC (permalink / raw) To: qemu-devel, kvm-devel 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); ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 2 2007-09-10 7:40 ` [Qemu-devel] expose host CPU features to guests: Take 2 Dan Kenigsberg @ 2007-09-10 11:47 ` Natalia Portillo 2007-09-10 12:01 ` Dan Kenigsberg 2007-09-24 17:41 ` [Qemu-devel] expose host CPU features to guests: Take 3 Dan Kenigsberg 1 sibling, 1 reply; 43+ messages in thread From: Natalia Portillo @ 2007-09-10 11:47 UTC (permalink / raw) To: qemu-devel 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/ ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 2 2007-09-10 11:47 ` Natalia Portillo @ 2007-09-10 12:01 ` Dan Kenigsberg 2007-09-07 16:18 ` Natalia Portillo 2007-09-10 17:16 ` Jamie Lokier 0 siblings, 2 replies; 43+ messages in thread From: Dan Kenigsberg @ 2007-09-10 12:01 UTC (permalink / raw) To: qemu-devel On Mon, Sep 10, 2007 at 12:47:51PM +0100, Natalia Portillo wrote: > I don't see in what is it useful without KVM/KQEMU. It is not. I tried to be clear about it in my post. Sorry for not being clearer. > And even with them there are some instructions that can't be accesible > without KQEMU/KVM prepared for them. I suspect this is true. For example, in my patch I blocked ACPI and VMX. Still, those features that ARE exposed to the guest, speed it up. Isn't it the Right Thing? > 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). I'm not sure I understand this comment. If you mean that -cpu should not expose a feature that is not emulated by qemu, I agree. Regards, Dan. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 2 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 1 sibling, 1 reply; 43+ messages in thread From: Natalia Portillo @ 2007-09-07 16:18 UTC (permalink / raw) To: qemu-devel Hi, > On Mon, Sep 10, 2007 at 12:47:51PM +0100, Natalia Portillo wrote: >> I don't see in what is it useful without KVM/KQEMU. > > It is not. I tried to be clear about it in my post. Sorry for not being > clearer. Ok now understood. >> And even with them there are some instructions that can't be accesible >> without KQEMU/KVM prepared for them. > > I suspect this is true. For example, in my patch I blocked ACPI and VMX. > Still, those features that ARE exposed to the guest, speed it up. Isn't > it the Right Thing? Well, I prefer to say "it is a right thing" :p >> 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). > > I'm not sure I understand this comment. If you mean that -cpu should not > expose a feature that is not emulated by qemu, I agree. I mean there should be a -cpu 8086, 286, 386, 486, pentium, pentium2, so on If you use 8086, qemu should behave as a 16-bit real-mode only processor doing an "unknown instruction" exception on anything not defined in the 8086 real processor. And so on. And also behave, at identification (CPUID, or legacy identification), like the selected CPU (for example -cpu 486 says family 4 model x stepping y, no l2 cache, so on) This can help some operating systems that hangs on unexpected identifications (NT 3.xx is the best example, as happens also on real hardware), and identifying badly implemented instructions on behave of cpu family (for example, in pentium an OS works flawlessly, in pentium2 an OS hangs just before sending CMOV instruction). If you implement it, count with my vote for inclusion :p (As I think x86, and x86-64 are the only ones archs that still dont implement -cpu in qemu. and remember, please, x86_64 only composes from pentium4 upwards and athlon64 upwards, no sense to behave like 386 in x86-64 emulator lol) Regards ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 2 2007-09-07 16:18 ` Natalia Portillo @ 2007-09-11 19:48 ` Luke -Jr 0 siblings, 0 replies; 43+ messages in thread From: Luke -Jr @ 2007-09-11 19:48 UTC (permalink / raw) To: qemu-devel On Friday 07 September 2007, Natalia Portillo wrote: > and remember, please, x86_64 only composes from pentium4 upwards and > athlon64 upwards, no sense to behave like 386 in x86-64 emulator lol) Actually, there is. Isn't the x86_64 emulator required to use kqemu on x86_64? Or does the -cpu 486 only apply to raw emulation mode anyway? ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 2 2007-09-10 12:01 ` Dan Kenigsberg 2007-09-07 16:18 ` Natalia Portillo @ 2007-09-10 17:16 ` Jamie Lokier 1 sibling, 0 replies; 43+ messages in thread From: Jamie Lokier @ 2007-09-10 17:16 UTC (permalink / raw) To: qemu-devel Dan Kenigsberg wrote: > On Mon, Sep 10, 2007 at 12:47:51PM +0100, Natalia Portillo wrote: > > I don't see in what is it useful without KVM/KQEMU. > > It is not. I tried to be clear about it in my post. Sorry for not being > clearer. Some day it may be useful without KVM/KQEMU, but not for a long time. There are instructions, for example MMX/SSE, which might be translated efficiently to single instructions on some host CPUs but to long function calls on others. But that won't happen until the translation back end is quite a lot more sophisticated than it is now. -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-10 7:40 ` [Qemu-devel] expose host CPU features to guests: Take 2 Dan Kenigsberg 2007-09-10 11:47 ` Natalia Portillo @ 2007-09-24 17:41 ` Dan Kenigsberg 2007-09-25 1:28 ` andrzej zaborowski 2007-10-07 12:38 ` [Qemu-devel] x86 -cpu option: Take 4 Dan Kenigsberg 1 sibling, 2 replies; 43+ messages in thread From: Dan Kenigsberg @ 2007-09-24 17:41 UTC (permalink / raw) To: qemu-devel, kvm-devel As with previous "Takes" 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. Another purpose for "Take 2" is to add the -cpu option to the x86 architecture, similarly to that of other architectures. -cpu 486, pentium, pentium2 and pentium3 are supported in addition to finer-grained features such as -cpu pentium,-mmx . As in Take 1, -cpu host exposes host features to guest. This patch exposes the requested CPU also right after RESET command, and not only in CPUID. Please let me know if you have more suggestions, Dan. ======================================= Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.342 diff -u -p -r1.342 vl.c --- vl.c 17 Sep 2007 21:25:20 -0000 1.342 +++ vl.c 24 Sep 2007 16:53:29 -0000 @@ -7694,6 +7694,8 @@ int main(int argc, char **argv) mips_cpu_list(stdout, &fprintf); #elif defined(TARGET_SPARC) sparc_cpu_list(stdout, &fprintf); +#elif defined(TARGET_I386) + x86_cpu_list(stdout, &fprintf); #endif exit(0); } else { Index: hw/pc.c =================================================================== RCS file: /sources/qemu/qemu/hw/pc.c,v retrieving revision 1.85 diff -u -p -r1.85 pc.c --- hw/pc.c 17 Sep 2007 08:09:47 -0000 1.85 +++ hw/pc.c 24 Sep 2007 16:53:29 -0000 @@ -666,7 +666,7 @@ static void pc_init1(int ram_size, int v 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, const char *cpu_model) { char buf[1024]; int ret, linux_boot, i; @@ -682,6 +682,13 @@ static void pc_init1(int ram_size, int v linux_boot = (kernel_filename != NULL); /* init CPUs */ + if (cpu_model == NULL) + cpu_model = "basic"; + + if (x86_find_cpu_by_name(cpu_model)) { + fprintf(stderr, "Unable to find x86 CPU definition\n"); + exit(1); + } for(i = 0; i < smp_cpus; i++) { env = cpu_init(); if (i != 0) @@ -948,7 +955,7 @@ static void pc_init_pci(int ram_size, in 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 +969,7 @@ static void pc_init_isa(int ram_size, in 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.48 diff -u -p -r1.48 cpu.h --- target-i386/cpu.h 23 Sep 2007 15:28:04 -0000 1.48 +++ target-i386/cpu.h 24 Sep 2007 16:53:30 -0000 @@ -274,23 +274,56 @@ #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 CPUID_EXT3_LAHF_LM (1 << 0) +#define CPUID_EXT3_CMP_LEG (1 << 1) #define CPUID_EXT3_SVM (1 << 2) +#define CPUID_EXT3_EXTAPIC (1 << 3) +#define CPUID_EXT3_CR8LEG (1 << 4) +#define CPUID_EXT3_ABM (1 << 5) +#define CPUID_EXT3_SSE4A (1 << 6) +#define CPUID_EXT3_MISALIGNSSE (1 << 7) +#define CPUID_EXT3_3DNOWPREFETCH (1 << 8) +#define CPUID_EXT3_OSVW (1 << 9) +#define CPUID_EXT3_IBS (1 << 10) #define EXCP00_DIVZ 0 #define EXCP01_SSTP 1 @@ -564,6 +597,9 @@ typedef struct CPUX86State { CPUX86State *cpu_x86_init(void); int cpu_x86_exec(CPUX86State *s); void cpu_x86_close(CPUX86State *s); +int x86_find_cpu_by_name (const unsigned char *name); +void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, + ...)); int cpu_get_pic_interrupt(CPUX86State *s); /* MSDOS compatibility mode FPU exception support */ void cpu_set_ferr(CPUX86State *s); Index: target-i386/helper2.c =================================================================== RCS file: /sources/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.52 diff -u -p -r1.52 helper2.c --- target-i386/helper2.c 23 Sep 2007 15:28:04 -0000 1.52 +++ target-i386/helper2.c 24 Sep 2007 16:53:30 -0000 @@ -46,6 +46,98 @@ int modify_ldt(int func, void *ptr, unsi #endif #endif /* USE_CODE_COPY */ +static struct x86_def_t *x86_cpu_def; +typedef struct x86_def_t x86_def_t; +static int cpu_x86_register (CPUX86State *env, const x86_def_t *def); + +/* 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, uint32_t *features, uint32_t *ext_features, uint32_t *ext2_features, uint32_t *ext3_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; + } + for ( i = 0 ; i < 32 ; i++ ) + if (x86_cap_flags[32*6+i] && !strcmp (flagname, x86_cap_flags[32*6+i])) { + *ext3_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); +} + +static void 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)); +} + CPUX86State *cpu_x86_init(void) { CPUX86State *env; @@ -80,71 +172,258 @@ CPUX86State *cpu_x86_init(void) asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7)); } #endif - { - int family, model, stepping; + cpu_x86_register(env, x86_cpu_def); + cpu_reset(env); +#ifdef USE_KQEMU + kqemu_init(env); +#endif + return env; +} + +struct x86_def_t { + const char *name; + uint32_t vendor1, vendor2, vendor3; + int family; + int model; + int stepping; + uint32_t features, ext_features, ext2_features, ext3_features; + uint32_t xlevel; + int hostlike; +}; + +#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \ + CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ + CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ + CPUID_PAE | CPUID_SEP | CPUID_APIC) +static x86_def_t x86_defs[] = { #ifdef TARGET_X86_64 - env->cpuid_vendor1 = 0x68747541; /* "Auth" */ - env->cpuid_vendor2 = 0x69746e65; /* "enti" */ - env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ - family = 6; - model = 2; - stepping = 3; + { + .name = "basic", + .vendor1 = 0x68747541, /* "Auth" */ + .vendor2 = 0x69746e65, /* "enti" */ + .vendor3 = 0x444d4163, /* "cAMD" */ + .family = 6, + .model = 2, + .stepping = 3, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36, + .ext_features = CPUID_EXT_SSE3, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .xlevel = 0x80000008, + }, #else + { + .name = "basic", + .family = 6, + .model = 3, + .stepping = 3, + .features = PPRO_FEATURES, + .ext_features = CPUID_EXT_SSE3, + .xlevel = 0, + }, +#endif + { + .name = "486", + .family = 4, + .model = 0, + .stepping = 0, + .features = 0x0000000B, + .xlevel = 0, + }, + { + .name = "pentium", + .family = 5, + .model = 4, + .stepping = 3, + .features = 0x008001BF, + .xlevel = 0, + }, + { + .name = "pentium2", + .family = 6, + .model = 5, + .stepping = 2, + .features = 0x0183F9FF, + .xlevel = 0, + }, + { + .name = "pentium3", + .family = 6, + .model = 7, + .stepping = 3, + .features = 0x0383F9FF, + .xlevel = 0, + }, + { + .name = "host", + .hostlike = 1, + }, +}; + +int x86_find_cpu_by_name(const unsigned char *cpu_model) +{ + int ret; + unsigned int i; + + char *s = strdup(cpu_model); + char *featurestr, *name = strtok(s, ","); + uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0; + uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0; + int family = -1, model = -1, stepping = -1; + + ret = -1; + x86_cpu_def = NULL; + for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) { + if (strcasecmp(name, x86_defs[i].name) == 0) { + x86_cpu_def = &x86_defs[i]; + ret = 0; + break; + } + } + if (!x86_cpu_def) + goto error; + + if (x86_cpu_def->hostlike) { + uint32_t ax, bx, cx, dx; + host_cpuid(0, &ax, &bx, &cx, &dx); + /* we ignore ax and take level=2 always */; + x86_cpu_def->vendor1 = bx; + x86_cpu_def->vendor2 = dx; + x86_cpu_def->vendor3 = cx; + + host_cpuid(1, &ax, &bx, &cx, &dx); + x86_cpu_def->stepping = ax & 0xf; + x86_cpu_def->model = (ax >> 4) & 0xf; + x86_cpu_def->family = ax >> 8; + x86_cpu_def->features = dx & ~CPUID_ACPI; /* acpi panics linux guests */ + x86_cpu_def->ext_features = cx & ~CPUID_EXT_VMX; /* vmx is not recursive */ + + /* host_cpuid(0x80000000, &ax, &bx, &cx, &dx); */ + x86_cpu_def->xlevel = 0x80000008 /*ax*/; + + host_cpuid(0x80000001, &ax, &bx, &cx, &dx); + /* svm is not recursive - unless Alexander Graf's SVM patch is applied */ + x86_cpu_def->ext3_features = cx & ~CPUID_EXT3_SVM; + x86_cpu_def->ext2_features = dx; + } + + featurestr = strtok(NULL, ","); + + while (featurestr) { + char *val; + if (featurestr[0] == '+') { + add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features); + } else if (featurestr[0] == '-') { + add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features); + } else if ((val = strchr(featurestr, '='))) { + *val = 0; val++; + if (!strcmp(featurestr, "family")) { + char *err; + family = strtol(val, &err, 10); + if (!*val || *err || family < 0) { + fprintf(stderr, "bad numerical value %s\n", val); + x86_cpu_def = 0; + goto error; + } + x86_cpu_def->family = family; + } else if (!strcmp(featurestr, "model")) { + char *err; + model = strtol(val, &err, 10); + if (!*val || *err || model < 0 || model > 0xf) { + fprintf(stderr, "bad numerical value %s\n", val); + x86_cpu_def = 0; + goto error; + } + x86_cpu_def->model = model; + } else if (!strcmp(featurestr, "stepping")) { + char *err; + stepping = strtol(val, &err, 10); + if (!*val || *err || stepping < 0 || stepping > 0xf) { + fprintf(stderr, "bad numerical value %s\n", val); + x86_cpu_def = 0; + goto error; + } + x86_cpu_def->stepping = stepping; + } else { + fprintf(stderr, "unregnized feature %s\n", featurestr); + x86_cpu_def = 0; + goto error; + } + } else { + fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); + x86_cpu_def = 0; + goto error; + } + featurestr = strtok(NULL, ","); + } + x86_cpu_def->features |= plus_features; + x86_cpu_def->ext_features |= plus_ext_features; + x86_cpu_def->ext2_features |= plus_ext2_features; + x86_cpu_def->ext3_features |= plus_ext3_features; + x86_cpu_def->features &= ~minus_features; + x86_cpu_def->ext_features &= ~minus_ext_features; + x86_cpu_def->ext2_features &= ~minus_ext2_features; + x86_cpu_def->ext3_features &= ~minus_ext3_features; + +error: + free(s); + return ret; +} + +void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) +{ + unsigned int i; + + for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) { + (*cpu_fprintf)(f, x86_defs[i].hostlike ? "x86 %16s Host-like CPU\n" + : "x86 %16s family %d model %d features %08x ext_features %08x ext2_features %08x ext3_features %08x\n", + x86_defs[i].name, + x86_defs[i].family, + x86_defs[i].model, + x86_defs[i].features, + x86_defs[i].ext_features, + x86_defs[i].ext2_features, + x86_defs[i].ext3_features); + } +} + +static int cpu_x86_register (CPUX86State *env, const x86_def_t *def) +{ + if (def->vendor1) { + env->cpuid_vendor1 = def->vendor1; + env->cpuid_vendor2 = def->vendor2; + env->cpuid_vendor3 = def->vendor3; + } else { env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ -#if 0 - /* pentium 75-200 */ - family = 5; - model = 2; - stepping = 11; -#else - /* pentium pro */ - family = 6; - model = 3; - stepping = 3; -#endif -#endif - env->cpuid_level = 2; - env->cpuid_version = (family << 8) | (model << 4) | stepping; - env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | - CPUID_TSC | CPUID_MSR | CPUID_MCE | - CPUID_CX8 | CPUID_PGE | CPUID_CMOV | - CPUID_PAT); - env->pat = 0x0007040600070406ULL; - env->cpuid_ext3_features = CPUID_EXT3_SVM; - 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 = 0x8000000e; - { - 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)); - } - } -#ifdef TARGET_X86_64 - /* currently not enabled for std i386 because not fully tested */ - env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); - env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; + } + env->cpuid_level = 2; + env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping; + env->cpuid_features = def->features; + env->pat = 0x0007040600070406ULL; + env->cpuid_ext_features = def->ext_features; + env->cpuid_ext2_features = def->ext2_features; + env->cpuid_xlevel = def->xlevel; + env->cpuid_ext3_features = def->ext3_features; + { + const char *model_id = "QEMU Virtual CPU version " QEMU_VERSION; + int c, len, i; - /* these features are needed for Win64 and aren't fully implemented */ - env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; - /* this feature is needed for Solaris and isn't fully implemented */ - env->cpuid_features |= CPUID_PSE36; -#endif + 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)); + } } - cpu_reset(env); -#ifdef USE_KQEMU - kqemu_init(env); -#endif - return env; + return 0; } /* NOTE: must be called outside the CPU execute loop */ @@ -184,7 +463,7 @@ void cpu_reset(CPUX86State *env) cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0); env->eip = 0xfff0; - env->regs[R_EDX] = 0x600; /* indicate P6 processor */ + env->regs[R_EDX] = env->cpuid_version; env->eflags = 0x2; ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 3 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:29 ` Fabrice Bellard 2007-10-07 12:38 ` [Qemu-devel] x86 -cpu option: Take 4 Dan Kenigsberg 1 sibling, 2 replies; 43+ messages in thread From: andrzej zaborowski @ 2007-09-25 1:28 UTC (permalink / raw) To: qemu-devel; +Cc: kvm-devel Hi, On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: > As with previous "Takes" 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. > > Another purpose for "Take 2" is to add the -cpu option to the x86 > architecture, similarly to that of other architectures. > -cpu 486, pentium, pentium2 and pentium3 are supported in addition to > finer-grained features such as -cpu pentium,-mmx . As in Take 1, > -cpu host exposes host features to guest. > > This patch exposes the requested CPU also right after RESET command, and > not only in CPUID. > > Please let me know if you have more suggestions, > > Dan. > > ======================================= > > Index: vl.c > =================================================================== > RCS file: /sources/qemu/qemu/vl.c,v > retrieving revision 1.342 > diff -u -p -r1.342 vl.c > --- vl.c 17 Sep 2007 21:25:20 -0000 1.342 > +++ vl.c 24 Sep 2007 16:53:29 -0000 > @@ -7694,6 +7694,8 @@ int main(int argc, char **argv) > mips_cpu_list(stdout, &fprintf); > #elif defined(TARGET_SPARC) > sparc_cpu_list(stdout, &fprintf); > +#elif defined(TARGET_I386) > + x86_cpu_list(stdout, &fprintf); > #endif > exit(0); > } else { > Index: hw/pc.c > =================================================================== > RCS file: /sources/qemu/qemu/hw/pc.c,v > retrieving revision 1.85 > diff -u -p -r1.85 pc.c > --- hw/pc.c 17 Sep 2007 08:09:47 -0000 1.85 > +++ hw/pc.c 24 Sep 2007 16:53:29 -0000 > @@ -666,7 +666,7 @@ static void pc_init1(int ram_size, int v > 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, const char *cpu_model) > { > char buf[1024]; > int ret, linux_boot, i; > @@ -682,6 +682,13 @@ static void pc_init1(int ram_size, int v > linux_boot = (kernel_filename != NULL); > > /* init CPUs */ > + if (cpu_model == NULL) > + cpu_model = "basic"; > + > + if (x86_find_cpu_by_name(cpu_model)) { > + fprintf(stderr, "Unable to find x86 CPU definition\n"); > + exit(1); > + } > for(i = 0; i < smp_cpus; i++) { > env = cpu_init(); > if (i != 0) > @@ -948,7 +955,7 @@ static void pc_init_pci(int ram_size, in > 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 +969,7 @@ static void pc_init_isa(int ram_size, in > 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.48 > diff -u -p -r1.48 cpu.h > --- target-i386/cpu.h 23 Sep 2007 15:28:04 -0000 1.48 > +++ target-i386/cpu.h 24 Sep 2007 16:53:30 -0000 > @@ -274,23 +274,56 @@ > #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 CPUID_EXT3_LAHF_LM (1 << 0) > +#define CPUID_EXT3_CMP_LEG (1 << 1) > #define CPUID_EXT3_SVM (1 << 2) > +#define CPUID_EXT3_EXTAPIC (1 << 3) > +#define CPUID_EXT3_CR8LEG (1 << 4) > +#define CPUID_EXT3_ABM (1 << 5) > +#define CPUID_EXT3_SSE4A (1 << 6) > +#define CPUID_EXT3_MISALIGNSSE (1 << 7) > +#define CPUID_EXT3_3DNOWPREFETCH (1 << 8) > +#define CPUID_EXT3_OSVW (1 << 9) > +#define CPUID_EXT3_IBS (1 << 10) > > #define EXCP00_DIVZ 0 > #define EXCP01_SSTP 1 > @@ -564,6 +597,9 @@ typedef struct CPUX86State { > CPUX86State *cpu_x86_init(void); > int cpu_x86_exec(CPUX86State *s); > void cpu_x86_close(CPUX86State *s); > +int x86_find_cpu_by_name (const unsigned char *name); > +void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, > + ...)); > int cpu_get_pic_interrupt(CPUX86State *s); > /* MSDOS compatibility mode FPU exception support */ > void cpu_set_ferr(CPUX86State *s); > Index: target-i386/helper2.c > =================================================================== > RCS file: /sources/qemu/qemu/target-i386/helper2.c,v > retrieving revision 1.52 > diff -u -p -r1.52 helper2.c > --- target-i386/helper2.c 23 Sep 2007 15:28:04 -0000 1.52 > +++ target-i386/helper2.c 24 Sep 2007 16:53:30 -0000 > @@ -46,6 +46,98 @@ int modify_ldt(int func, void *ptr, unsi > #endif > #endif /* USE_CODE_COPY */ > > +static struct x86_def_t *x86_cpu_def; > +typedef struct x86_def_t x86_def_t; > +static int cpu_x86_register (CPUX86State *env, const x86_def_t *def); > + > +/* 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, uint32_t *features, uint32_t *ext_features, uint32_t *ext2_features, uint32_t *ext3_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; > + } > + for ( i = 0 ; i < 32 ; i++ ) > + if (x86_cap_flags[32*6+i] && !strcmp (flagname, x86_cap_flags[32*6+i])) { > + *ext3_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); > +} > + > +static void 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)); > +} I haven't really read through the rest of your code but this piece appears to be outside any #ifdef/#endif so it will only build on x86. Regards ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 1:28 ` andrzej zaborowski @ 2007-09-25 8:48 ` Dan Kenigsberg 2007-09-25 9:01 ` Avi Kivity 2007-09-25 9:29 ` Fabrice Bellard 1 sibling, 1 reply; 43+ messages in thread From: Dan Kenigsberg @ 2007-09-25 8:48 UTC (permalink / raw) To: andrzej zaborowski; +Cc: kvm-devel, qemu-devel On Tue, Sep 25, 2007 at 03:28:24AM +0200, andrzej zaborowski wrote: > Hi, > > On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: > > As with previous "Takes" of this patch, its purpose is to expose host > > +{ > > + asm("cpuid" > > + : "=a" (*ax), > > + "=b" (*bx), > > + "=c" (*cx), > > + "=d" (*dx) > > + : "a" (function)); > > +} > > I haven't really read through the rest of your code but this piece > appears to be outside any #ifdef/#endif so it will only build on x86. I might be missing something here, but isn't not being on the TARGET_PATH of Makefile.target enough? I don't see #ifdef TARGET_I386 elsewhere under target-i386. I don't mind adding extra protection, I just be happy to better understand the whats and whys. Dan. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 8:48 ` [kvm-devel] " Dan Kenigsberg @ 2007-09-25 9:01 ` Avi Kivity 2007-09-25 9:19 ` J. Mayer 0 siblings, 1 reply; 43+ messages in thread From: Avi Kivity @ 2007-09-25 9:01 UTC (permalink / raw) To: Dan Kenigsberg; +Cc: kvm-devel, qemu-devel Dan Kenigsberg wrote: > On Tue, Sep 25, 2007 at 03:28:24AM +0200, andrzej zaborowski wrote: > >> Hi, >> >> On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: >> >>> As with previous "Takes" of this patch, its purpose is to expose host >>> +{ >>> + asm("cpuid" >>> + : "=a" (*ax), >>> + "=b" (*bx), >>> + "=c" (*cx), >>> + "=d" (*dx) >>> + : "a" (function)); >>> +} >>> >> I haven't really read through the rest of your code but this piece >> appears to be outside any #ifdef/#endif so it will only build on x86. >> > > I might be missing something here, but isn't not being on the > TARGET_PATH of Makefile.target enough? I don't see #ifdef TARGET_I386 > elsewhere under target-i386. I don't mind adding extra protection, I > just be happy to better understand the whats and whys. > target-i386 means the guest will run i386 instructions, but the host can be something else (say, powerpc). Nothing else uses host instructions in that directory, so no protection was necessary before. -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 9:01 ` Avi Kivity @ 2007-09-25 9:19 ` J. Mayer 2007-09-25 9:31 ` Avi Kivity 0 siblings, 1 reply; 43+ messages in thread From: J. Mayer @ 2007-09-25 9:19 UTC (permalink / raw) To: qemu-devel; +Cc: Dan Kenigsberg, kvm-devel On Tue, 2007-09-25 at 11:01 +0200, Avi Kivity wrote: > Dan Kenigsberg wrote: > > On Tue, Sep 25, 2007 at 03:28:24AM +0200, andrzej zaborowski wrote: > > > >> Hi, > >> > >> On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: > >> > >>> As with previous "Takes" of this patch, its purpose is to expose host > >>> +{ > >>> + asm("cpuid" > >>> + : "=a" (*ax), > >>> + "=b" (*bx), > >>> + "=c" (*cx), > >>> + "=d" (*dx) > >>> + : "a" (function)); > >>> +} > >>> > >> I haven't really read through the rest of your code but this piece > >> appears to be outside any #ifdef/#endif so it will only build on x86. > >> > > > > I might be missing something here, but isn't not being on the > > TARGET_PATH of Makefile.target enough? I don't see #ifdef TARGET_I386 > > elsewhere under target-i386. I don't mind adding extra protection, I > > just be happy to better understand the whats and whys. > > > > target-i386 means the guest will run i386 instructions, but the host can > be something else (say, powerpc). > > Nothing else uses host instructions in that directory, so no protection > was necessary before. I've got a remark about this: why this has to be added to the Qemu code ? Imho, all is needed is an implementation of the -cpu option for x86/x86_64 target. Then, an external tool (even a shell script) can be used to determine what is the host CPU if you want to select the exact same CPU to be emulated in Qemu. It seems to me that trying to do so is out of the scope of Qemu code and just add unneeded complexity. Regards. -- J. Mayer <l_indien@magic.fr> Never organized ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 9:19 ` J. Mayer @ 2007-09-25 9:31 ` Avi Kivity 2007-09-25 10:40 ` Avi Kivity 2007-09-25 12:51 ` Paul Brook 0 siblings, 2 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-25 9:31 UTC (permalink / raw) To: J. Mayer; +Cc: kvm-devel, qemu-devel J. Mayer wrote: > On Tue, 2007-09-25 at 11:01 +0200, Avi Kivity wrote: > >> Dan Kenigsberg wrote: >> >>> On Tue, Sep 25, 2007 at 03:28:24AM +0200, andrzej zaborowski wrote: >>> >>> >>>> Hi, >>>> >>>> On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: >>>> >>>> >>>>> As with previous "Takes" of this patch, its purpose is to expose host >>>>> +{ >>>>> + asm("cpuid" >>>>> + : "=a" (*ax), >>>>> + "=b" (*bx), >>>>> + "=c" (*cx), >>>>> + "=d" (*dx) >>>>> + : "a" (function)); >>>>> +} >>>>> >>>>> >>>> I haven't really read through the rest of your code but this piece >>>> appears to be outside any #ifdef/#endif so it will only build on x86. >>>> >>>> >>> I might be missing something here, but isn't not being on the >>> TARGET_PATH of Makefile.target enough? I don't see #ifdef TARGET_I386 >>> elsewhere under target-i386. I don't mind adding extra protection, I >>> just be happy to better understand the whats and whys. >>> >>> >> target-i386 means the guest will run i386 instructions, but the host can >> be something else (say, powerpc). >> >> Nothing else uses host instructions in that directory, so no protection >> was necessary before. >> > > I've got a remark about this: why this has to be added to the Qemu > code ? > Imho, all is needed is an implementation of the -cpu option for > x86/x86_64 target. Then, an external tool (even a shell script) can be > used to determine what is the host CPU if you want to select the exact > same CPU to be emulated in Qemu. It seems to me that trying to do so is > out of the scope of Qemu code and just add unneeded complexity. > Indeed for regular qemu this is useless. But it is useful for kqemu (for which there is support in mainline qemu), and for kvm (which we hope to merge one day). -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 9:31 ` Avi Kivity @ 2007-09-25 10:40 ` Avi Kivity 2007-09-25 11:09 ` J. Mayer 2007-09-25 12:51 ` Paul Brook 1 sibling, 1 reply; 43+ messages in thread From: Avi Kivity @ 2007-09-25 10:40 UTC (permalink / raw) To: J. Mayer; +Cc: kvm-devel, qemu-devel Avi Kivity wrote: >>> >>> >> I've got a remark about this: why this has to be added to the Qemu >> code ? >> Imho, all is needed is an implementation of the -cpu option for >> x86/x86_64 target. Then, an external tool (even a shell script) can be >> used to determine what is the host CPU if you want to select the exact >> same CPU to be emulated in Qemu. It seems to me that trying to do so is >> out of the scope of Qemu code and just add unneeded complexity. >> >> > > Indeed for regular qemu this is useless. But it is useful for kqemu > (for which there is support in mainline qemu), and for kvm (which we > hope to merge one day). > > Actually (as Izik Eidus reminds me), this isn't very useful for kqemu as it can't trap cpuid in all circumstances. So this is mainly useful for kvm. I hope it will be applied regardless of that, as there is agreement that kvm support should be merged. I'd much rather pull the feature from qemu rather than carry it as an additional patch. -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 10:40 ` Avi Kivity @ 2007-09-25 11:09 ` J. Mayer 2007-09-25 11:36 ` Avi Kivity 0 siblings, 1 reply; 43+ messages in thread From: J. Mayer @ 2007-09-25 11:09 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel, qemu-devel On Tue, 2007-09-25 at 12:40 +0200, Avi Kivity wrote: > Avi Kivity wrote: > >>> > >>> > >> I've got a remark about this: why this has to be added to the Qemu > >> code ? > >> Imho, all is needed is an implementation of the -cpu option for > >> x86/x86_64 target. Then, an external tool (even a shell script) can be > >> used to determine what is the host CPU if you want to select the exact > >> same CPU to be emulated in Qemu. It seems to me that trying to do so is > >> out of the scope of Qemu code and just add unneeded complexity. > >> > >> > > > > Indeed for regular qemu this is useless. But it is useful for kqemu > > (for which there is support in mainline qemu), and for kvm (which we > > hope to merge one day). > > > > > > Actually (as Izik Eidus reminds me), this isn't very useful for kqemu as > it can't trap cpuid in all circumstances. > > So this is mainly useful for kvm. I hope it will be applied regardless > of that, as there is agreement that kvm support should be merged. I'd > much rather pull the feature from qemu rather than carry it as an > additional patch. Still I don't understand why it's usefull to put it inside the emulator and why: # qemu -cpu `guess_host_cpu` would not do the work properly. Adding a specific case for '-cpu host' seems useless to me. And this way of doing potentially work for any family of emulated targets, without any modification in Qemu. If the string returned by 'guess_host_cpu' is not recognized for the specific target you used it with, Qemu just stops telling it cannot find this CPU model, no more, no less. The only case it could be interresting, imho, is if you do not allow the -cpu option in KVM case and force the cpu model instead using this function. This behavior does not seem to be great idea to me. Or maybe I missed something ? -- J. Mayer <l_indien@magic.fr> Never organized ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 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 0 siblings, 2 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-25 11:36 UTC (permalink / raw) To: J. Mayer; +Cc: kvm-devel, qemu-devel J. Mayer wrote: > On Tue, 2007-09-25 at 12:40 +0200, Avi Kivity wrote: > >> Avi Kivity wrote: >> >>>>> >>>>> >>>>> >>>> I've got a remark about this: why this has to be added to the Qemu >>>> code ? >>>> Imho, all is needed is an implementation of the -cpu option for >>>> x86/x86_64 target. Then, an external tool (even a shell script) can be >>>> used to determine what is the host CPU if you want to select the exact >>>> same CPU to be emulated in Qemu. It seems to me that trying to do so is >>>> out of the scope of Qemu code and just add unneeded complexity. >>>> >>>> >>>> >>> Indeed for regular qemu this is useless. But it is useful for kqemu >>> (for which there is support in mainline qemu), and for kvm (which we >>> hope to merge one day). >>> >>> >>> >> Actually (as Izik Eidus reminds me), this isn't very useful for kqemu as >> it can't trap cpuid in all circumstances. >> >> So this is mainly useful for kvm. I hope it will be applied regardless >> of that, as there is agreement that kvm support should be merged. I'd >> much rather pull the feature from qemu rather than carry it as an >> additional patch. >> > > Still I don't understand why it's usefull to put it inside the emulator > and why: > # qemu -cpu `guess_host_cpu` > would not do the work properly. Adding a specific case for '-cpu host' > seems useless to me. > And this way of doing potentially work for any family of emulated > targets, without any modification in Qemu. If the string returned by > 'guess_host_cpu' is not recognized for the specific target you used it > with, Qemu just stops telling it cannot find this CPU model, no more, no > less. > It's a usability issue. I agree your suggestion would work, but I'd like the default for kvm to be using the host cpu features, whereas managed environments would specify some subset to enable live migration. > The only case it could be interresting, imho, is if you do not allow the > -cpu option in KVM case and force the cpu model instead using this > function. This behavior does not seem to be great idea to me. > I think we can move the host cpu checks to kvm-specific code, since it is not useful for kqemu. So, running qemu without any parameters would use host capabilities if kvm is available and the default qemu cpu if not. The -cpu option can be used to override this if necessary. -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 11:36 ` Avi Kivity @ 2007-09-25 12:05 ` Fabrice Bellard 2007-09-25 13:07 ` Jocelyn Mayer 1 sibling, 0 replies; 43+ messages in thread From: Fabrice Bellard @ 2007-09-25 12:05 UTC (permalink / raw) To: qemu-devel; +Cc: kvm-devel, J. Mayer Avi Kivity wrote: > J. Mayer wrote: > >>On Tue, 2007-09-25 at 12:40 +0200, Avi Kivity wrote: >> >> >>>Avi Kivity wrote: >>> >>> >>>>>> >>>>>> >>>>>> >>>>> >>>>>I've got a remark about this: why this has to be added to the Qemu >>>>>code ? >>>>>Imho, all is needed is an implementation of the -cpu option for >>>>>x86/x86_64 target. Then, an external tool (even a shell script) can be >>>>>used to determine what is the host CPU if you want to select the exact >>>>>same CPU to be emulated in Qemu. It seems to me that trying to do so is >>>>>out of the scope of Qemu code and just add unneeded complexity. >>>>> >>>>> >>>>> >>>> >>>>Indeed for regular qemu this is useless. But it is useful for kqemu >>>>(for which there is support in mainline qemu), and for kvm (which we >>>>hope to merge one day). >>>> >>>> >>>> >>> >>>Actually (as Izik Eidus reminds me), this isn't very useful for kqemu as >>>it can't trap cpuid in all circumstances. >>> >>>So this is mainly useful for kvm. I hope it will be applied regardless >>>of that, as there is agreement that kvm support should be merged. I'd >>>much rather pull the feature from qemu rather than carry it as an >>>additional patch. >>> >> >>Still I don't understand why it's usefull to put it inside the emulator >>and why: >># qemu -cpu `guess_host_cpu` >>would not do the work properly. Adding a specific case for '-cpu host' >>seems useless to me. >>And this way of doing potentially work for any family of emulated >>targets, without any modification in Qemu. If the string returned by >>'guess_host_cpu' is not recognized for the specific target you used it >>with, Qemu just stops telling it cannot find this CPU model, no more, no >>less. >> > > > It's a usability issue. I agree your suggestion would work, but I'd > like the default for kvm to be using the host cpu features, whereas > managed environments would specify some subset to enable live migration. > > >>The only case it could be interresting, imho, is if you do not allow the >>-cpu option in KVM case and force the cpu model instead using this >>function. This behavior does not seem to be great idea to me. >> > > > I think we can move the host cpu checks to kvm-specific code, since it > is not useful for kqemu. > > So, running qemu without any parameters would use host capabilities if > kvm is available and the default qemu cpu if not. The -cpu option can > be used to override this if necessary. Rectification: this is useful for kqemu too. I strongly suggest to look at kqemu.c:kqemu_update_cpuid() ! Moreover I believe that using the same CPU as host can be useful for pure emulation too, for example if code to do cache profiling is added. Regards, Fabrice. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 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 ` (2 more replies) 1 sibling, 3 replies; 43+ messages in thread From: Jocelyn Mayer @ 2007-09-25 13:07 UTC (permalink / raw) To: Avi Kivity; +Cc: kvm-devel, qemu-devel On Tue, 2007-09-25 at 13:36 +0200, Avi Kivity wrote: > J. Mayer wrote: > > On Tue, 2007-09-25 at 12:40 +0200, Avi Kivity wrote: > > > >> Avi Kivity wrote: > >> > >>>>> > >>>>> > >>>>> > >>>> I've got a remark about this: why this has to be added to the Qemu > >>>> code ? > >>>> Imho, all is needed is an implementation of the -cpu option for > >>>> x86/x86_64 target. Then, an external tool (even a shell script) can be > >>>> used to determine what is the host CPU if you want to select the exact > >>>> same CPU to be emulated in Qemu. It seems to me that trying to do so is > >>>> out of the scope of Qemu code and just add unneeded complexity. > >>>> > >>>> > >>>> > >>> Indeed for regular qemu this is useless. But it is useful for kqemu > >>> (for which there is support in mainline qemu), and for kvm (which we > >>> hope to merge one day). > >>> > >>> > >>> > >> Actually (as Izik Eidus reminds me), this isn't very useful for kqemu as > >> it can't trap cpuid in all circumstances. > >> > >> So this is mainly useful for kvm. I hope it will be applied regardless > >> of that, as there is agreement that kvm support should be merged. I'd > >> much rather pull the feature from qemu rather than carry it as an > >> additional patch. > >> > > > > Still I don't understand why it's usefull to put it inside the emulator > > and why: > > # qemu -cpu `guess_host_cpu` > > would not do the work properly. Adding a specific case for '-cpu host' > > seems useless to me. > > And this way of doing potentially work for any family of emulated > > targets, without any modification in Qemu. If the string returned by > > 'guess_host_cpu' is not recognized for the specific target you used it > > with, Qemu just stops telling it cannot find this CPU model, no more, no > > less. > > > > It's a usability issue. I agree your suggestion would work, but I'd > like the default for kvm to be using the host cpu features, whereas > managed environments would specify some subset to enable live migration. > > > The only case it could be interresting, imho, is if you do not allow the > > -cpu option in KVM case and force the cpu model instead using this > > function. This behavior does not seem to be great idea to me. > > > > I think we can move the host cpu checks to kvm-specific code, since it > is not useful for kqemu. > > So, running qemu without any parameters would use host capabilities if > kvm is available and the default qemu cpu if not. The -cpu option can > be used to override this if necessary. Well, it may be needed to integrate the "-cpu host" option. But I think it's a really bad idea that running qemu without the -cpu option would not act the same on different host. When I want to test qemu with the same command line, I want it to behave exactly the same, whatever the host I'm running on, like any other tool. Think about gcc, for example, if you launch it without option, it compiles for a generic CPU. If you want to tune the generated code, even for the host you're running on, you have to use -mcpu/-march/-mtune. Using one command line always have gives the same result. Then, my opinion is that running qemu without any -cpu option should always use a default target. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 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 2 siblings, 0 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-25 13:12 UTC (permalink / raw) To: l_indien; +Cc: kvm-devel, qemu-devel Jocelyn Mayer wrote: > On Tue, 2007-09-25 at 13:36 +0200, Avi Kivity wrote: > >> J. Mayer wrote: >> >>> On Tue, 2007-09-25 at 12:40 +0200, Avi Kivity wrote: >>> >>> >>>> Avi Kivity wrote: >>>> >>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>> I've got a remark about this: why this has to be added to the Qemu >>>>>> code ? >>>>>> Imho, all is needed is an implementation of the -cpu option for >>>>>> x86/x86_64 target. Then, an external tool (even a shell script) can be >>>>>> used to determine what is the host CPU if you want to select the exact >>>>>> same CPU to be emulated in Qemu. It seems to me that trying to do so is >>>>>> out of the scope of Qemu code and just add unneeded complexity. >>>>>> >>>>>> >>>>>> >>>>>> >>>>> Indeed for regular qemu this is useless. But it is useful for kqemu >>>>> (for which there is support in mainline qemu), and for kvm (which we >>>>> hope to merge one day). >>>>> >>>>> >>>>> >>>>> >>>> Actually (as Izik Eidus reminds me), this isn't very useful for kqemu as >>>> it can't trap cpuid in all circumstances. >>>> >>>> So this is mainly useful for kvm. I hope it will be applied regardless >>>> of that, as there is agreement that kvm support should be merged. I'd >>>> much rather pull the feature from qemu rather than carry it as an >>>> additional patch. >>>> >>>> >>> Still I don't understand why it's usefull to put it inside the emulator >>> and why: >>> # qemu -cpu `guess_host_cpu` >>> would not do the work properly. Adding a specific case for '-cpu host' >>> seems useless to me. >>> And this way of doing potentially work for any family of emulated >>> targets, without any modification in Qemu. If the string returned by >>> 'guess_host_cpu' is not recognized for the specific target you used it >>> with, Qemu just stops telling it cannot find this CPU model, no more, no >>> less. >>> >>> >> It's a usability issue. I agree your suggestion would work, but I'd >> like the default for kvm to be using the host cpu features, whereas >> managed environments would specify some subset to enable live migration. >> >> >>> The only case it could be interresting, imho, is if you do not allow the >>> -cpu option in KVM case and force the cpu model instead using this >>> function. This behavior does not seem to be great idea to me. >>> >>> >> I think we can move the host cpu checks to kvm-specific code, since it >> is not useful for kqemu. >> >> So, running qemu without any parameters would use host capabilities if >> kvm is available and the default qemu cpu if not. The -cpu option can >> be used to override this if necessary. >> > > Well, it may be needed to integrate the "-cpu host" option. > But I think it's a really bad idea that running qemu without the -cpu > option would not act the same on different host. When I want to test > qemu with the same command line, I want it to behave exactly the same, > whatever the host I'm running on, like any other tool. Think about gcc, > for example, if you launch it without option, it compiles for a generic > CPU. If you want to tune the generated code, even for the host you're > running on, you have to use -mcpu/-march/-mtune. Using one command line > always have gives the same result. > Then, my opinion is that running qemu without any -cpu option should > always use a default target. > That's a valid usage model. For many kvm users, however, the primary reason to run qemu is to get the performance that kvm provides, so they'd like to see host cpuid as the default. Maybe a .qemurc can help here. -- Any sufficiently difficult bug is indistinguishable from a feature. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 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 2 siblings, 0 replies; 43+ messages in thread From: Dan Kenigsberg @ 2007-09-25 13:27 UTC (permalink / raw) To: Jocelyn Mayer; +Cc: kvm-devel, qemu-devel On Tue, Sep 25, 2007 at 03:07:44PM +0200, Jocelyn Mayer wrote: > > So, running qemu without any parameters would use host capabilities if > > kvm is available and the default qemu cpu if not. The -cpu option can > > be used to override this if necessary. > > Well, it may be needed to integrate the "-cpu host" option. > But I think it's a really bad idea that running qemu without the -cpu > option would not act the same on different host. When I want to test > qemu with the same command line, I want it to behave exactly the same, > whatever the host I'm running on, like any other tool. Think about gcc, > for example, if you launch it without option, it compiles for a generic > CPU. If you want to tune the generated code, even for the host you're > running on, you have to use -mcpu/-march/-mtune. Using one command line > always have gives the same result. > Then, my opinion is that running qemu without any -cpu option should > always use a default target. Note that in "take 3" the default is indeed to expose the "basic" default cpu features if no -cpu is specified. One must add -cpu host in order to read and expose the host cpuid. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 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 2 siblings, 1 reply; 43+ messages in thread From: Jamie Lokier @ 2007-09-25 15:54 UTC (permalink / raw) To: l_indien, qemu-devel Jocelyn Mayer wrote: > Well, it may be needed to integrate the "-cpu host" option. > But I think it's a really bad idea that running qemu without the -cpu > option would not act the same on different host. When I want to test > qemu with the same command line, I want it to behave exactly the same, > whatever the host I'm running on, like any other tool. Think about gcc, > for example, if you launch it without option, it compiles for a generic > CPU. If you want to tune the generated code, even for the host you're > running on, you have to use -mcpu/-march/-mtune. Using one command line > always have gives the same result. > Then, my opinion is that running qemu without any -cpu option should > always use a default target. A major feature of qemu is reproducible behaviour. This is especially important when resuming snapshots or booting pre-installed images for testing things. A major feature of kvm/kqemu is performance. But not always performance at the expense of reproducibility. Sometimes you want to use kvm/kqemu to make qemu as fast as possible while still behaving the same with some image. Where someone wants performance to have precedence, it's easy enough to advise "use -cpu host" for that. Where someone wants performance, but reproducibility to have precedence, it would be more awkward to have to advise "use -cpu list,of,common,features". I think reproducibility is something which needs to be working by default. This is because people make images before they decide to move them to other hosts, and often before they would consider at all issues about host differences, and making images is sometimes a lot of work. Images should be portable among hosts by default. But, if we say that the default is a baseline CPU, and there's a "-cpu host" option to maximise performance, then we have to decide what features the baseline CPU has. Obviously a 386 isn't very useful for emulation any more - many OSes won't run on it. Then, if we change our mind about the default baseline CPU, then we've lost reproducibility for old images anyway. That's an argument for storing the emulated CPU features in images. If that's done, then for image portability among hosts, it is not so important that the default CPU have only the features which are native to every host. Instead, the critical thing is simply that it has only features which are either native or can be emulated on every host. E.g. TSC is in this category. -- Jamie ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 15:54 ` Jamie Lokier @ 2007-09-25 16:15 ` Avi Kivity 0 siblings, 0 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-25 16:15 UTC (permalink / raw) To: qemu-devel; +Cc: l_indien Jamie Lokier wrote: > Jocelyn Mayer wrote: > >> Well, it may be needed to integrate the "-cpu host" option. >> But I think it's a really bad idea that running qemu without the -cpu >> option would not act the same on different host. When I want to test >> qemu with the same command line, I want it to behave exactly the same, >> whatever the host I'm running on, like any other tool. Think about gcc, >> for example, if you launch it without option, it compiles for a generic >> CPU. If you want to tune the generated code, even for the host you're >> running on, you have to use -mcpu/-march/-mtune. Using one command line >> always have gives the same result. >> Then, my opinion is that running qemu without any -cpu option should >> always use a default target. >> > > A major feature of qemu is reproducible behaviour. This is especially > important when resuming snapshots or booting pre-installed images for > testing things. > > A major feature of kvm/kqemu is performance. But not always > performance at the expense of reproducibility. Sometimes you want to > use kvm/kqemu to make qemu as fast as possible while still behaving > the same with some image. > > Where someone wants performance to have precedence, it's easy enough > to advise "use -cpu host" for that. > > Where someone wants performance, but reproducibility to have > precedence, it would be more awkward to have to advise "use -cpu > list,of,common,features". > Or maybe "-cpu baseline" or some other neutral word. > I think reproducibility is something which needs to be working by > default. This is because people make images before they decide to > move them to other hosts, and often before they would consider at all > issues about host differences, and making images is sometimes a lot of > work. Images should be portable among hosts by default. > > But, if we say that the default is a baseline CPU, and there's a "-cpu > host" option to maximise performance, then we have to decide what > features the baseline CPU has. Obviously a 386 isn't very useful for > emulation any more - many OSes won't run on it. > > The baseline cpu should be whatever qemu supports today. > Then, if we change our mind about the default baseline CPU, then we've > lost reproducibility for old images anyway. > > That's an argument for storing the emulated CPU features in images. > That's another thread -- I want memory size and network configuration in there too :) > If that's done, then for image portability among hosts, it is not so > important that the default CPU have only the features which > are native to every host. Instead, the critical thing is simply that > it has only features which are either native or can be emulated on > every host. E.g. TSC is in this category. > Qemu is used to support three different user classes which have different requirements. Developers want reproducibility and control, so -cpu baseline should be the default for them. Home users want speed to run Windows or test distros, so -cpu host and kvm should be the default for them. Managed deployments want something in between, so they'd specify -cpu feature,feature and won't care about the default. We can make it a ./configure option. I suspect distros will want to set -cpu host as default as their users primarily care about speed. -- Any sufficiently difficult bug is indistinguishable from a feature. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 9:31 ` Avi Kivity 2007-09-25 10:40 ` Avi Kivity @ 2007-09-25 12:51 ` Paul Brook 2007-09-25 13:13 ` Avi Kivity 1 sibling, 1 reply; 43+ messages in thread From: Paul Brook @ 2007-09-25 12:51 UTC (permalink / raw) To: qemu-devel; +Cc: kvm-devel, J. Mayer On Tuesday 25 September 2007, Avi Kivity wrote: > J. Mayer wrote: > > On Tue, 2007-09-25 at 11:01 +0200, Avi Kivity wrote: > >> Dan Kenigsberg wrote: > >>> On Tue, Sep 25, 2007 at 03:28:24AM +0200, andrzej zaborowski wrote: > >>>> Hi, > >>>> > >>>> On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: > >>>>> As with previous "Takes" of this patch, its purpose is to expose host > >>>>> +{ > >>>>> + asm("cpuid" > >>>>> + : "=a" (*ax), > >>>>> + "=b" (*bx), > >>>>> + "=c" (*cx), > >>>>> + "=d" (*dx) > >>>>> + : "a" (function)); > >>>>> +} > >>>> > Indeed for regular qemu this is useless. But it is useful for kqemu > (for which there is support in mainline qemu), and for kvm (which we > hope to merge one day). And, as discussed before, it should be asking the hypervisor what features it supports instead of trying to guess from the cpuid output. Paul ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [kvm-devel] [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 12:51 ` Paul Brook @ 2007-09-25 13:13 ` Avi Kivity 0 siblings, 0 replies; 43+ messages in thread From: Avi Kivity @ 2007-09-25 13:13 UTC (permalink / raw) To: Paul Brook; +Cc: kvm-devel, J. Mayer, qemu-devel Paul Brook wrote: >> Indeed for regular qemu this is useless. But it is useful for kqemu >> (for which there is support in mainline qemu), and for kvm (which we >> hope to merge one day). >> > > And, as discussed before, it should be asking the hypervisor what features it > supports instead of trying to guess from the cpuid output. > Agreed. -- Any sufficiently difficult bug is indistinguishable from a feature. ^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [Qemu-devel] expose host CPU features to guests: Take 3 2007-09-25 1:28 ` andrzej zaborowski 2007-09-25 8:48 ` [kvm-devel] " Dan Kenigsberg @ 2007-09-25 9:29 ` Fabrice Bellard 1 sibling, 0 replies; 43+ messages in thread From: Fabrice Bellard @ 2007-09-25 9:29 UTC (permalink / raw) To: qemu-devel andrzej zaborowski wrote: > Hi, > > On 24/09/2007, Dan Kenigsberg <danken@qumranet.com> wrote: > >>As with previous "Takes" 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. >> >>Another purpose for "Take 2" is to add the -cpu option to the x86 >>architecture, similarly to that of other architectures. >>-cpu 486, pentium, pentium2 and pentium3 are supported in addition to >>finer-grained features such as -cpu pentium,-mmx . As in Take 1, >>-cpu host exposes host features to guest. >> >>This patch exposes the requested CPU also right after RESET command, and >>not only in CPUID. >> >>Please let me know if you have more suggestions, >> >>Dan. >>[...] > I haven't really read through the rest of your code but this piece > appears to be outside any #ifdef/#endif so it will only build on x86. > > Regards A few remarks: 1) I cannot accept GPL code in target-i386, so the code from the Linux kernel must be removed or rewritten. 2) cpuid is already defined in kqemu.c, so it would be better to use it (I consider this is not a blocking point though). 3) For the future, I suggest that the function cpu_xxx_register() is removed and that the parameter xxx_def_t is added to cpu_xxx_init(). Rationale: I see no point in initializing a CPU without specifying its exact model and I am not sure that cpu_xxx_register() can be called once some code is executed. Regards, Fabrice. ^ permalink raw reply [flat|nested] 43+ messages in thread
* [Qemu-devel] x86 -cpu option: Take 4 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-10-07 12:38 ` Dan Kenigsberg 1 sibling, 0 replies; 43+ messages in thread From: Dan Kenigsberg @ 2007-10-07 12:38 UTC (permalink / raw) To: qemu-devel, kvm-devel Hi, Due to comments on "Take 3", I rewrote the feature name list according to Intel's and AMD's specs in order not to contaminate target-i386 with GPL code. More importantly - the "host" cpu type is dropped. It will be added, as a kvm-specific code, in a future patch. I'd be happy to hear if patch is applicable in its current minimalistic form this, or that more changes should be made. Thanks, Dan. Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.346 diff -u -p -r1.346 vl.c --- vl.c 5 Oct 2007 13:08:34 -0000 1.346 +++ vl.c 7 Oct 2007 12:34:45 -0000 @@ -7696,6 +7696,8 @@ int main(int argc, char **argv) mips_cpu_list(stdout, &fprintf); #elif defined(TARGET_SPARC) sparc_cpu_list(stdout, &fprintf); +#elif defined(TARGET_I386) + x86_cpu_list(stdout, &fprintf); #endif exit(0); } else { Index: hw/pc.c =================================================================== RCS file: /sources/qemu/qemu/hw/pc.c,v retrieving revision 1.86 diff -u -p -r1.86 pc.c --- hw/pc.c 5 Oct 2007 13:08:35 -0000 1.86 +++ hw/pc.c 7 Oct 2007 12:34:46 -0000 @@ -666,7 +666,7 @@ static void pc_init1(int ram_size, int v 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, const char *cpu_model) { char buf[1024]; int ret, linux_boot, i; @@ -682,6 +682,13 @@ static void pc_init1(int ram_size, int v linux_boot = (kernel_filename != NULL); /* init CPUs */ + if (cpu_model == NULL) + cpu_model = "basic"; + + if (x86_find_cpu_by_name(cpu_model)) { + fprintf(stderr, "Unable to find x86 CPU definition\n"); + exit(1); + } for(i = 0; i < smp_cpus; i++) { env = cpu_init(); if (i != 0) @@ -950,7 +957,7 @@ static void pc_init_pci(int ram_size, in 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, @@ -964,7 +971,7 @@ static void pc_init_isa(int ram_size, in 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.50 diff -u -p -r1.50 cpu.h --- target-i386/cpu.h 27 Sep 2007 16:44:31 -0000 1.50 +++ target-i386/cpu.h 7 Oct 2007 12:34:46 -0000 @@ -274,23 +274,56 @@ #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 CPUID_EXT3_LAHF_LM (1 << 0) +#define CPUID_EXT3_CMP_LEG (1 << 1) #define CPUID_EXT3_SVM (1 << 2) +#define CPUID_EXT3_EXTAPIC (1 << 3) +#define CPUID_EXT3_CR8LEG (1 << 4) +#define CPUID_EXT3_ABM (1 << 5) +#define CPUID_EXT3_SSE4A (1 << 6) +#define CPUID_EXT3_MISALIGNSSE (1 << 7) +#define CPUID_EXT3_3DNOWPREFETCH (1 << 8) +#define CPUID_EXT3_OSVW (1 << 9) +#define CPUID_EXT3_IBS (1 << 10) #define EXCP00_DIVZ 0 #define EXCP01_SSTP 1 @@ -564,6 +597,9 @@ typedef struct CPUX86State { CPUX86State *cpu_x86_init(void); int cpu_x86_exec(CPUX86State *s); void cpu_x86_close(CPUX86State *s); +int x86_find_cpu_by_name (const unsigned char *name); +void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, + ...)); int cpu_get_pic_interrupt(CPUX86State *s); /* MSDOS compatibility mode FPU exception support */ void cpu_set_ferr(CPUX86State *s); Index: target-i386/helper2.c =================================================================== RCS file: /sources/qemu/qemu/target-i386/helper2.c,v retrieving revision 1.52 diff -u -p -r1.52 helper2.c --- target-i386/helper2.c 23 Sep 2007 15:28:04 -0000 1.52 +++ target-i386/helper2.c 7 Oct 2007 12:34:46 -0000 @@ -46,6 +46,64 @@ int modify_ldt(int func, void *ptr, unsi #endif #endif /* USE_CODE_COPY */ +static struct x86_def_t *x86_cpu_def; +typedef struct x86_def_t x86_def_t; +static int cpu_x86_register (CPUX86State *env, const x86_def_t *def); + +static void add_flagname_to_bitmaps(char *flagname, uint32_t *features, uint32_t *ext_features, uint32_t *ext2_features, uint32_t *ext3_features) +{ + int i; + /* feature flags taken from "Intel Processor Identification and the CPUID + * Instruction" and AMD's "CPUID Specification". In cases of disagreement + * about feature names, the Linux name is used. */ + const char *feature_name[] = { + "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", + "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", + "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */, NULL, "ds" /* Intel dts */, "acpi", "mmx", + "fxsr", "sse", "sse2", "ss", "ht" /* Intel htt */, "tm", "ia64", "pbe", + }; + const char *ext_feature_name[] = { + "pni" /* Intel,AMD sse3 */, NULL, NULL, "monitor", "ds_cpl", "vmx", NULL /* Linux 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, + }; + const char *ext2_feature_name[] = { + "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", + "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall", "mttr", "pge", "mca", "cmov", + "pat", "pse36", NULL, NULL /* Linux mp */, "nx" /* Intel xd */, NULL, "mmxext", "mmx", + "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp", NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow", + }; + const char *ext3_feature_name[] = { + "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */, "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse", + "3dnowprefetch", "osvw", NULL /* Linux ibs */, NULL, "skinit", "wdt", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + }; + + for ( i = 0 ; i < 32 ; i++ ) + if (feature_name[i] && !strcmp (flagname, feature_name[i])) { + *features |= 1 << i; + return; + } + for ( i = 0 ; i < 32 ; i++ ) + if (ext_feature_name[i] && !strcmp (flagname, ext_feature_name[i])) { + *ext_features |= 1 << i; + return; + } + for ( i = 0 ; i < 32 ; i++ ) + if (ext2_feature_name[i] && !strcmp (flagname, ext2_feature_name[i])) { + *ext2_features |= 1 << i; + return; + } + for ( i = 0 ; i < 32 ; i++ ) + if (ext3_features[i] && !strcmp (flagname, ext3_feature_name[i])) { + *ext3_features |= 1 << i; + return; + } + fprintf(stderr, "CPU feature %s not found\n", flagname); +} + CPUX86State *cpu_x86_init(void) { CPUX86State *env; @@ -80,71 +138,220 @@ CPUX86State *cpu_x86_init(void) asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7)); } #endif - { - int family, model, stepping; + cpu_x86_register(env, x86_cpu_def); + cpu_reset(env); +#ifdef USE_KQEMU + kqemu_init(env); +#endif + return env; +} + +struct x86_def_t { + const char *name; + uint32_t vendor1, vendor2, vendor3; + int family; + int model; + int stepping; + uint32_t features, ext_features, ext2_features, ext3_features; + uint32_t xlevel; +}; + +#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \ + CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \ + CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \ + CPUID_PAE | CPUID_SEP | CPUID_APIC) +static x86_def_t x86_defs[] = { #ifdef TARGET_X86_64 - env->cpuid_vendor1 = 0x68747541; /* "Auth" */ - env->cpuid_vendor2 = 0x69746e65; /* "enti" */ - env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ - family = 6; - model = 2; - stepping = 3; + { + .name = "basic", + .vendor1 = 0x68747541, /* "Auth" */ + .vendor2 = 0x69746e65, /* "enti" */ + .vendor3 = 0x444d4163, /* "cAMD" */ + .family = 6, + .model = 2, + .stepping = 3, + .features = PPRO_FEATURES | + /* these features are needed for Win64 and aren't fully implemented */ + CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | + /* this feature is needed for Solaris and isn't fully implemented */ + CPUID_PSE36, + .ext_features = CPUID_EXT_SSE3, + .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .ext3_features = CPUID_EXT3_SVM, + .xlevel = 0x80000008, + }, #else + { + .name = "basic", + .family = 6, + .model = 3, + .stepping = 3, + .features = PPRO_FEATURES, + .ext_features = CPUID_EXT_SSE3, + .xlevel = 0, + }, +#endif + { + .name = "486", + .family = 4, + .model = 0, + .stepping = 0, + .features = 0x0000000B, + .xlevel = 0, + }, + { + .name = "pentium", + .family = 5, + .model = 4, + .stepping = 3, + .features = 0x008001BF, + .xlevel = 0, + }, + { + .name = "pentium2", + .family = 6, + .model = 5, + .stepping = 2, + .features = 0x0183F9FF, + .xlevel = 0, + }, + { + .name = "pentium3", + .family = 6, + .model = 7, + .stepping = 3, + .features = 0x0383F9FF, + .xlevel = 0, + }, +}; + +int x86_find_cpu_by_name(const unsigned char *cpu_model) +{ + int ret; + unsigned int i; + + char *s = strdup(cpu_model); + char *featurestr, *name = strtok(s, ","); + uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0; + uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0; + int family = -1, model = -1, stepping = -1; + + ret = -1; + x86_cpu_def = NULL; + for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) { + if (strcasecmp(name, x86_defs[i].name) == 0) { + x86_cpu_def = &x86_defs[i]; + ret = 0; + break; + } + } + if (!x86_cpu_def) + goto error; + + featurestr = strtok(NULL, ","); + + while (featurestr) { + char *val; + if (featurestr[0] == '+') { + add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features); + } else if (featurestr[0] == '-') { + add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features); + } else if ((val = strchr(featurestr, '='))) { + *val = 0; val++; + if (!strcmp(featurestr, "family")) { + char *err; + family = strtol(val, &err, 10); + if (!*val || *err || family < 0) { + fprintf(stderr, "bad numerical value %s\n", val); + x86_cpu_def = 0; + goto error; + } + x86_cpu_def->family = family; + } else if (!strcmp(featurestr, "model")) { + char *err; + model = strtol(val, &err, 10); + if (!*val || *err || model < 0 || model > 0xf) { + fprintf(stderr, "bad numerical value %s\n", val); + x86_cpu_def = 0; + goto error; + } + x86_cpu_def->model = model; + } else if (!strcmp(featurestr, "stepping")) { + char *err; + stepping = strtol(val, &err, 10); + if (!*val || *err || stepping < 0 || stepping > 0xf) { + fprintf(stderr, "bad numerical value %s\n", val); + x86_cpu_def = 0; + goto error; + } + x86_cpu_def->stepping = stepping; + } else { + fprintf(stderr, "unregnized feature %s\n", featurestr); + x86_cpu_def = 0; + goto error; + } + } else { + fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); + x86_cpu_def = 0; + goto error; + } + featurestr = strtok(NULL, ","); + } + x86_cpu_def->features |= plus_features; + x86_cpu_def->ext_features |= plus_ext_features; + x86_cpu_def->ext2_features |= plus_ext2_features; + x86_cpu_def->ext3_features |= plus_ext3_features; + x86_cpu_def->features &= ~minus_features; + x86_cpu_def->ext_features &= ~minus_ext_features; + x86_cpu_def->ext2_features &= ~minus_ext2_features; + x86_cpu_def->ext3_features &= ~minus_ext3_features; + +error: + free(s); + return ret; +} + +void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) +{ + unsigned int i; + + for (i = 0; i < sizeof(x86_defs) / sizeof(x86_def_t); i++) + (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name); +} + +int cpu_x86_register (CPUX86State *env, const x86_def_t *def) +{ + if (def->vendor1) { + env->cpuid_vendor1 = def->vendor1; + env->cpuid_vendor2 = def->vendor2; + env->cpuid_vendor3 = def->vendor3; + } else { env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ -#if 0 - /* pentium 75-200 */ - family = 5; - model = 2; - stepping = 11; -#else - /* pentium pro */ - family = 6; - model = 3; - stepping = 3; -#endif -#endif - env->cpuid_level = 2; - env->cpuid_version = (family << 8) | (model << 4) | stepping; - env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | - CPUID_TSC | CPUID_MSR | CPUID_MCE | - CPUID_CX8 | CPUID_PGE | CPUID_CMOV | - CPUID_PAT); - env->pat = 0x0007040600070406ULL; - env->cpuid_ext3_features = CPUID_EXT3_SVM; - 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 = 0x8000000e; - { - 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_level = 2; + env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping; + env->cpuid_features = def->features; + env->pat = 0x0007040600070406ULL; + env->cpuid_ext_features = def->ext_features; + env->cpuid_ext2_features = def->ext2_features; + env->cpuid_xlevel = def->xlevel; + env->cpuid_ext3_features = def->ext3_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)); } -#ifdef TARGET_X86_64 - /* currently not enabled for std i386 because not fully tested */ - env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); - env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX; - - /* these features are needed for Win64 and aren't fully implemented */ - env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; - /* this feature is needed for Solaris and isn't fully implemented */ - env->cpuid_features |= CPUID_PSE36; -#endif } - cpu_reset(env); -#ifdef USE_KQEMU - kqemu_init(env); -#endif - return env; + return 0; } /* NOTE: must be called outside the CPU execute loop */ @@ -184,7 +391,7 @@ void cpu_reset(CPUX86State *env) cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0); env->eip = 0xfff0; - env->regs[R_EDX] = 0x600; /* indicate P6 processor */ + env->regs[R_EDX] = env->cpuid_version; env->eflags = 0x2; ^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2007-10-07 12:41 UTC | newest] Thread overview: 43+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 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
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).