qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] expose host CPU features to guests: Take 3


From: andrzej zaborowski
Subject: Re: [Qemu-devel] expose host CPU features to guests: Take 3
Date: Tue, 25 Sep 2007 03:28:24 +0200

Hi,

On 24/09/2007, Dan Kenigsberg <address@hidden> 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]