debuggers.hg

changeset 22425:c553d3035fd5

tools: libxl: fix cpuid compilation errors for ia64

ia64 does not have cpuid. So break out cpuid-related functions into a
separate file, with stubs for ia64.

Signed-off-by: KUWAMURA Shin'ya <kuwa@jp.fujitsu.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author KUWAMURA Shin'ya <kuwa@jp.fujitsu.com>
date Tue Nov 09 17:43:12 2010 +0000 (2010-11-09)
parents 7188d1e4b0e1
children a56433935704
files tools/libxl/Makefile tools/libxl/libxl.c tools/libxl/libxl.h tools/libxl/libxl_cpuid.c tools/libxl/libxl_dom.c tools/libxl/libxl_nocpuid.c
line diff
     1.1 --- a/tools/libxl/Makefile	Tue Nov 09 12:00:05 2010 +0000
     1.2 +++ b/tools/libxl/Makefile	Tue Nov 09 17:43:12 2010 +0000
     1.3 @@ -26,6 +26,8 @@ LIBXL_OBJS-y += libxl_blktap2.o
     1.4  else
     1.5  LIBXL_OBJS-y += libxl_noblktap2.o
     1.6  endif
     1.7 +LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o
     1.8 +LIBXL_OBJS-$(CONFIG_IA64) += libxl_nocpuid.o
     1.9  
    1.10  LIBXL_OBJS = flexarray.o libxl.o libxl_pci.o libxl_dom.o libxl_exec.o libxl_xshelp.o libxl_device.o libxl_internal.o libxl_utils.o $(LIBXL_OBJS-y)
    1.11  LIBXL_OBJS += _libxl_types.o
     2.1 --- a/tools/libxl/libxl.c	Tue Nov 09 12:00:05 2010 +0000
     2.2 +++ b/tools/libxl/libxl.c	Tue Nov 09 17:43:12 2010 +0000
     2.3 @@ -102,21 +102,6 @@ void libxl_key_value_list_destroy(libxl_
     2.4      free(kvl);
     2.5  }
     2.6  
     2.7 -void libxl_cpuid_destroy(libxl_cpuid_policy_list *p_cpuid_list)
     2.8 -{
     2.9 -    int i, j;
    2.10 -    libxl_cpuid_policy_list cpuid_list = *p_cpuid_list;
    2.11 -
    2.12 -    if (cpuid_list == NULL)
    2.13 -        return;
    2.14 -    for (i = 0; cpuid_list[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
    2.15 -        for (j = 0; j < 4; j++)
    2.16 -            if (cpuid_list[i].policy[j] != NULL)
    2.17 -                free(cpuid_list[i].policy[j]);
    2.18 -    }
    2.19 -    return;
    2.20 -}
    2.21 -
    2.22  /******************************************************************************/
    2.23  
    2.24  int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
    2.25 @@ -3517,285 +3502,6 @@ uint32_t libxl_vm_get_start_time(libxl_c
    2.26      return ret;
    2.27  }
    2.28  
    2.29 -#define CPUID_REG_INV 0
    2.30 -#define CPUID_REG_EAX 1
    2.31 -#define CPUID_REG_EBX 2
    2.32 -#define CPUID_REG_ECX 3
    2.33 -#define CPUID_REG_EDX 4
    2.34 -
    2.35 -/* mapping CPUID features to names
    2.36 - * holds a "name" for each feature, specified by the "leaf" number (and an
    2.37 - * optional "subleaf" in ECX), the "reg"ister (EAX-EDX) used and a number of
    2.38 - * bits starting with "bit" and being "length" bits long.
    2.39 - * Used for the static structure describing all features.
    2.40 - */
    2.41 -struct cpuid_flags {
    2.42 -    char* name;
    2.43 -    uint32_t leaf;
    2.44 -    uint32_t subleaf;
    2.45 -    int reg;
    2.46 -    int bit;
    2.47 -    int length;
    2.48 -};
    2.49 -
    2.50 -/* go through the dynamic array finding the entry for a specified leaf.
    2.51 - * if no entry exists, allocate one and return that.
    2.52 - */
    2.53 -static libxl_cpuid_policy_list cpuid_find_match(libxl_cpuid_policy_list *list,
    2.54 -                                          uint32_t leaf, uint32_t subleaf)
    2.55 -{
    2.56 -    int i = 0;
    2.57 -
    2.58 -    if (*list != NULL) {
    2.59 -        for (i = 0; (*list)[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
    2.60 -            if ((*list)[i].input[0] == leaf && (*list)[i].input[1] == subleaf)
    2.61 -                return *list + i;
    2.62 -        }
    2.63 -    }
    2.64 -    *list = realloc(*list, sizeof((*list)[0]) * (i + 2));
    2.65 -    (*list)[i].input[0] = leaf;
    2.66 -    (*list)[i].input[1] = subleaf;
    2.67 -    memset((*list)[i].policy, 0, 4 * sizeof(char*));
    2.68 -    (*list)[i + 1].input[0] = XEN_CPUID_INPUT_UNUSED;
    2.69 -    return *list + i;
    2.70 -}
    2.71 -
    2.72 -/* parse a single key=value pair and translate it into the libxc
    2.73 - * used interface using 32-characters strings for each register.
    2.74 - * Will overwrite earlier entries and thus can be called multiple
    2.75 - * times.
    2.76 - */
    2.77 -int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
    2.78 -{
    2.79 -#define NA XEN_CPUID_INPUT_UNUSED
    2.80 -    struct cpuid_flags cpuid_flags[] = {
    2.81 -        {"maxleaf",      0x00000000, NA, CPUID_REG_EAX,  0, 32},
    2.82 -      /* the following two entries are subject to tweaking later in the code */
    2.83 -        {"family",       0x00000001, NA, CPUID_REG_EAX,  8,  8},
    2.84 -        {"model",        0x00000001, NA, CPUID_REG_EAX,  4,  8},
    2.85 -        {"stepping",     0x00000001, NA, CPUID_REG_EAX,  0,  4},
    2.86 -        {"localapicid",  0x00000001, NA, CPUID_REG_EBX, 24,  8},
    2.87 -        {"proccount",    0x00000001, NA, CPUID_REG_EBX, 16,  8},
    2.88 -        {"clflush",      0x00000001, NA, CPUID_REG_EBX,  8,  8},
    2.89 -        {"brandid",      0x00000001, NA, CPUID_REG_EBX,  0,  8},
    2.90 -        {"f16c",         0x00000001, NA, CPUID_REG_ECX, 29,  1},
    2.91 -        {"avx",          0x00000001, NA, CPUID_REG_ECX, 28,  1},
    2.92 -        {"osxsave",      0x00000001, NA, CPUID_REG_ECX, 27,  1},
    2.93 -        {"xsave",        0x00000001, NA, CPUID_REG_ECX, 26,  1},
    2.94 -        {"aes",          0x00000001, NA, CPUID_REG_ECX, 25,  1},
    2.95 -        {"popcnt",       0x00000001, NA, CPUID_REG_ECX, 23,  1},
    2.96 -        {"movbe",        0x00000001, NA, CPUID_REG_ECX, 22,  1},
    2.97 -        {"x2apic",       0x00000001, NA, CPUID_REG_ECX, 21,  1},
    2.98 -        {"sse4.2",       0x00000001, NA, CPUID_REG_ECX, 20,  1},
    2.99 -        {"sse4.1",       0x00000001, NA, CPUID_REG_ECX, 19,  1},
   2.100 -        {"dca",          0x00000001, NA, CPUID_REG_ECX, 18,  1},
   2.101 -        {"pdcm",         0x00000001, NA, CPUID_REG_ECX, 15,  1},
   2.102 -        {"xtpr",         0x00000001, NA, CPUID_REG_ECX, 14,  1},
   2.103 -        {"cmpxchg16",    0x00000001, NA, CPUID_REG_ECX, 13,  1},
   2.104 -        {"cntxid",       0x00000001, NA, CPUID_REG_ECX, 10,  1},
   2.105 -        {"ssse3",        0x00000001, NA, CPUID_REG_ECX,  9,  1},
   2.106 -        {"tm2",          0x00000001, NA, CPUID_REG_ECX,  8,  1},
   2.107 -        {"est",          0x00000001, NA, CPUID_REG_ECX,  7,  1},
   2.108 -        {"smx",          0x00000001, NA, CPUID_REG_ECX,  6,  1},
   2.109 -        {"vmx",          0x00000001, NA, CPUID_REG_ECX,  5,  1},
   2.110 -        {"dscpl",        0x00000001, NA, CPUID_REG_ECX,  4,  1},
   2.111 -        {"monitor",      0x00000001, NA, CPUID_REG_ECX,  3,  1},
   2.112 -        {"dtes64",       0x00000001, NA, CPUID_REG_ECX,  2,  1},
   2.113 -        {"sse3",         0x00000001, NA, CPUID_REG_ECX,  0,  1},
   2.114 -        {"pbe",          0x00000001, NA, CPUID_REG_EDX, 31,  1},
   2.115 -        {"ia64",         0x00000001, NA, CPUID_REG_EDX, 30,  1},
   2.116 -        {"tm",           0x00000001, NA, CPUID_REG_EDX, 29,  1},
   2.117 -        {"htt",          0x00000001, NA, CPUID_REG_EDX, 28,  1},
   2.118 -        {"ss",           0x00000001, NA, CPUID_REG_EDX, 27,  1},
   2.119 -        {"sse2",         0x00000001, NA, CPUID_REG_EDX, 26,  1},
   2.120 -        {"sse",          0x00000001, NA, CPUID_REG_EDX, 25,  1},
   2.121 -        {"fxsr",         0x00000001, NA, CPUID_REG_EDX, 24,  1},
   2.122 -        {"mmx",          0x00000001, NA, CPUID_REG_EDX, 23,  1},
   2.123 -        {"acpi",         0x00000001, NA, CPUID_REG_EDX, 22,  1},
   2.124 -        {"ds",           0x00000001, NA, CPUID_REG_EDX, 21,  1},
   2.125 -        {"clfsh",        0x00000001, NA, CPUID_REG_EDX, 19,  1},
   2.126 -        {"psn",          0x00000001, NA, CPUID_REG_EDX, 18,  1},
   2.127 -        {"pse36",        0x00000001, NA, CPUID_REG_EDX, 17,  1},
   2.128 -        {"pat",          0x00000001, NA, CPUID_REG_EDX, 16,  1},
   2.129 -        {"cmov",         0x00000001, NA, CPUID_REG_EDX, 15,  1},
   2.130 -        {"mca",          0x00000001, NA, CPUID_REG_EDX, 14,  1},
   2.131 -        {"pge",          0x00000001, NA, CPUID_REG_EDX, 13,  1},
   2.132 -        {"mtrr",         0x00000001, NA, CPUID_REG_EDX, 12,  1},
   2.133 -        {"sysenter",     0x00000001, NA, CPUID_REG_EDX, 11,  1},
   2.134 -        {"apic",         0x00000001, NA, CPUID_REG_EDX,  9,  1},
   2.135 -        {"cmpxchg8",     0x00000001, NA, CPUID_REG_EDX,  8,  1},
   2.136 -        {"mce",          0x00000001, NA, CPUID_REG_EDX,  7,  1},
   2.137 -        {"pae",          0x00000001, NA, CPUID_REG_EDX,  6,  1},
   2.138 -        {"msr",          0x00000001, NA, CPUID_REG_EDX,  5,  1},
   2.139 -        {"tsc",          0x00000001, NA, CPUID_REG_EDX,  4,  1},
   2.140 -        {"pse",          0x00000001, NA, CPUID_REG_EDX,  3,  1},
   2.141 -        {"de",           0x00000001, NA, CPUID_REG_EDX,  2,  1},
   2.142 -        {"vme",          0x00000001, NA, CPUID_REG_EDX,  1,  1},
   2.143 -        {"fpu",          0x00000001, NA, CPUID_REG_EDX,  0,  1},
   2.144 -        {"topoext",      0x80000001, NA, CPUID_REG_ECX, 22,  1},
   2.145 -        {"tbm",          0x80000001, NA, CPUID_REG_ECX, 21,  1},
   2.146 -        {"nodeid",       0x80000001, NA, CPUID_REG_ECX, 19,  1},
   2.147 -        {"fma4",         0x80000001, NA, CPUID_REG_ECX, 16,  1},
   2.148 -        {"lwp",          0x80000001, NA, CPUID_REG_ECX, 15,  1},
   2.149 -        {"wdt",          0x80000001, NA, CPUID_REG_ECX, 13,  1},
   2.150 -        {"skinit",       0x80000001, NA, CPUID_REG_ECX, 12,  1},
   2.151 -        {"xop",          0x80000001, NA, CPUID_REG_ECX, 11,  1},
   2.152 -        {"ibs",          0x80000001, NA, CPUID_REG_ECX, 10,  1},
   2.153 -        {"osvw",         0x80000001, NA, CPUID_REG_ECX, 10,  1},
   2.154 -        {"3dnowprefetch",0x80000001, NA, CPUID_REG_ECX,  8,  1},
   2.155 -        {"misalignsse",  0x80000001, NA, CPUID_REG_ECX,  7,  1},
   2.156 -        {"sse4a",        0x80000001, NA, CPUID_REG_ECX,  6,  1},
   2.157 -        {"abm",          0x80000001, NA, CPUID_REG_ECX,  5,  1},
   2.158 -        {"altmovcr8",    0x80000001, NA, CPUID_REG_ECX,  4,  1},
   2.159 -        {"extapic",      0x80000001, NA, CPUID_REG_ECX,  3,  1},
   2.160 -        {"svm",          0x80000001, NA, CPUID_REG_ECX,  2,  1},
   2.161 -        {"cmplegacy",    0x80000001, NA, CPUID_REG_ECX,  1,  1},
   2.162 -        {"lahfsahf",     0x80000001, NA, CPUID_REG_ECX,  0,  1},
   2.163 -        {"3dnow",        0x80000001, NA, CPUID_REG_EDX, 31,  1},
   2.164 -        {"3dnowext",     0x80000001, NA, CPUID_REG_EDX, 30,  1},
   2.165 -        {"lm",           0x80000001, NA, CPUID_REG_EDX, 29,  1},
   2.166 -        {"rdtscp",       0x80000001, NA, CPUID_REG_EDX, 27,  1},
   2.167 -        {"page1gb",      0x80000001, NA, CPUID_REG_EDX, 26,  1},
   2.168 -        {"ffxsr",        0x80000001, NA, CPUID_REG_EDX, 25,  1},
   2.169 -        {"mmxext",       0x80000001, NA, CPUID_REG_EDX, 22,  1},
   2.170 -        {"nx",           0x80000001, NA, CPUID_REG_EDX, 20,  1},
   2.171 -        {"syscall",      0x80000001, NA, CPUID_REG_EDX, 11,  1},
   2.172 -        {"procpkg",      0x00000004,  0, CPUID_REG_EAX, 26,  6},
   2.173 -        {"apicidsize",   0x80000008, NA, CPUID_REG_ECX, 12,  4},
   2.174 -        {"nc",           0x80000008, NA, CPUID_REG_ECX,  0,  8},
   2.175 -
   2.176 -        {NULL, 0, CPUID_REG_INV, 0, 0}
   2.177 -    };
   2.178 -#undef NA
   2.179 -    char *sep, *val, *endptr;
   2.180 -    int i;
   2.181 -    struct cpuid_flags *flag;
   2.182 -    struct libxl__cpuid_policy *entry;
   2.183 -    unsigned long num;
   2.184 -    char flags[33], *resstr;
   2.185 -
   2.186 -    sep = strchr(str, '=');
   2.187 -    if (sep == NULL) {
   2.188 -        return 1;
   2.189 -    } else {
   2.190 -        val = sep + 1;
   2.191 -    }
   2.192 -    for (flag = cpuid_flags; flag->name != NULL; flag++) {
   2.193 -        if(!strncmp(str, flag->name, sep - str) && flag->name[sep - str] == 0)
   2.194 -            break;
   2.195 -    }
   2.196 -    if (flag->name == NULL) {
   2.197 -        return 2;
   2.198 -    }
   2.199 -    entry = cpuid_find_match(cpuid, flag->leaf, flag->subleaf);
   2.200 -    resstr = entry->policy[flag->reg - 1];
   2.201 -    if (resstr == NULL) {
   2.202 -        resstr = strdup("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
   2.203 -    }
   2.204 -    num = strtoull(val, &endptr, 0);
   2.205 -    flags[flag->length] = 0;
   2.206 -    if (endptr != val) {
   2.207 -        /* is this was a valid number, write the binary form into the string */
   2.208 -        for (i = 0; i < flag->length; i++) {
   2.209 -            flags[flag->length - 1 - i] = "01"[!!(num & (1 << i))];
   2.210 -        }
   2.211 -    } else {
   2.212 -        switch(val[0]) {
   2.213 -        case 'x': case 'k': case 's':
   2.214 -            memset(flags, val[0], flag->length);
   2.215 -            break;
   2.216 -        default:
   2.217 -            return 3;
   2.218 -        }
   2.219 -    }
   2.220 -    /* the family and model entry is potentially split up across
   2.221 -     * two fields in Fn0000_0001_EAX, so handle them here separately.
   2.222 -     */
   2.223 -    if (!strncmp(str, "family", sep - str)) {
   2.224 -        if (num < 16) {
   2.225 -            memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
   2.226 -            memcpy(resstr + (32 - 8) - 20, "00000000", 8);
   2.227 -        } else {
   2.228 -            num -= 15;
   2.229 -            memcpy(resstr + (32 - 4) - flag->bit, "1111", 4);
   2.230 -            for (i = 0; i < 7; i++) {
   2.231 -                flags[7 - i] = "01"[num & 1];
   2.232 -                num >>= 1;
   2.233 -            }
   2.234 -            memcpy(resstr + (32 - 8) - 20, flags, 8);
   2.235 -        }
   2.236 -    } else if (!strncmp(str, "model", sep - str)) {
   2.237 -        memcpy(resstr + (32 - 4) - 16, flags, 4);
   2.238 -        memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
   2.239 -    } else {
   2.240 -        memcpy(resstr + (32 - flag->length) - flag->bit, flags,
   2.241 -               flag->length);
   2.242 -    }
   2.243 -    entry->policy[flag->reg - 1] = resstr;
   2.244 -
   2.245 -    return 0;
   2.246 -}
   2.247 -
   2.248 -/* parse a single list item from the legacy Python xend syntax, where
   2.249 - * the strings for each register were directly exposed to the user.
   2.250 - * Used for maintaining compatibility with older config files
   2.251 - */
   2.252 -int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
   2.253 -                                  const char* str)
   2.254 -{
   2.255 -    char *endptr;
   2.256 -    unsigned long value;
   2.257 -    uint32_t leaf, subleaf = XEN_CPUID_INPUT_UNUSED;
   2.258 -    struct libxl__cpuid_policy *entry;
   2.259 -
   2.260 -    /* parse the leaf number */
   2.261 -    value = strtoul(str, &endptr, 0);
   2.262 -    if (str == endptr) {
   2.263 -        return 1;
   2.264 -    }
   2.265 -    leaf = value;
   2.266 -    /* check for an optional subleaf number */
   2.267 -    if (*endptr == ',') {
   2.268 -        str = endptr + 1;
   2.269 -        value = strtoul(str, &endptr, 0);
   2.270 -        if (str == endptr) {
   2.271 -            return 2;
   2.272 -        }
   2.273 -        subleaf = value;
   2.274 -    }
   2.275 -    if (*endptr != ':') {
   2.276 -        return 3;
   2.277 -    }
   2.278 -    str = endptr + 1;
   2.279 -    entry = cpuid_find_match(cpuid, leaf, subleaf);
   2.280 -    for (str = endptr + 1; *str != 0;) {
   2.281 -        if (str[0] != 'e' || str[2] != 'x') {
   2.282 -            return 4;
   2.283 -        }
   2.284 -        value = str[1] - 'a';
   2.285 -        endptr = strchr(str, '=');
   2.286 -        if (value < 0 || value > 3 || endptr == NULL) {
   2.287 -            return 4;
   2.288 -        }
   2.289 -        str = endptr + 1;
   2.290 -        endptr = strchr(str, ',');
   2.291 -        if (endptr == NULL) {
   2.292 -            endptr = strchr(str, 0);
   2.293 -        }
   2.294 -        if (endptr - str != 32) {
   2.295 -            return 5;
   2.296 -        }
   2.297 -        entry->policy[value] = calloc(32 + 1, 1);
   2.298 -        strncpy(entry->policy[value], str, 32);
   2.299 -        entry->policy[value][32] = 0;
   2.300 -        if (*endptr == 0) {
   2.301 -            break;
   2.302 -        }
   2.303 -        for (str = endptr + 1; *str == ' ' || *str == '\n'; str++);
   2.304 -    }
   2.305 -    return 0;
   2.306 -}
   2.307 -
   2.308  char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
   2.309  {
   2.310      int rc;
     3.1 --- a/tools/libxl/libxl.h	Tue Nov 09 12:00:05 2010 +0000
     3.2 +++ b/tools/libxl/libxl.h	Tue Nov 09 17:43:12 2010 +0000
     3.3 @@ -421,6 +421,9 @@ int libxl_device_pci_parse_bdf(libxl_ctx
     3.4  int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str);
     3.5  int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
     3.6                                    const char* str);
     3.7 +void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid);
     3.8 +void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
     3.9 +		     libxl_cpuid_policy_list cpuid);
    3.10  
    3.11  /*
    3.12   * Functions for allowing users of libxl to store private data
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxl/libxl_cpuid.c	Tue Nov 09 17:43:12 2010 +0000
     4.3 @@ -0,0 +1,327 @@
     4.4 +/*
     4.5 + * This program is free software; you can redistribute it and/or modify
     4.6 + * it under the terms of the GNU Lesser General Public License as published
     4.7 + * by the Free Software Foundation; version 2.1 only. with the special
     4.8 + * exception on linking described in file LICENSE.
     4.9 + *
    4.10 + * This program is distributed in the hope that it will be useful,
    4.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.13 + * GNU Lesser General Public License for more details.
    4.14 + */
    4.15 +
    4.16 +#include <string.h>
    4.17 +
    4.18 +#include "libxl.h"
    4.19 +#include "libxl_osdeps.h"
    4.20 +#include "libxl_internal.h"
    4.21 +
    4.22 +void libxl_cpuid_destroy(libxl_cpuid_policy_list *p_cpuid_list)
    4.23 +{
    4.24 +    int i, j;
    4.25 +    libxl_cpuid_policy_list cpuid_list = *p_cpuid_list;
    4.26 +
    4.27 +    if (cpuid_list == NULL)
    4.28 +        return;
    4.29 +    for (i = 0; cpuid_list[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
    4.30 +        for (j = 0; j < 4; j++)
    4.31 +            if (cpuid_list[i].policy[j] != NULL)
    4.32 +                free(cpuid_list[i].policy[j]);
    4.33 +    }
    4.34 +    return;
    4.35 +}
    4.36 +
    4.37 +#define CPUID_REG_INV 0
    4.38 +#define CPUID_REG_EAX 1
    4.39 +#define CPUID_REG_EBX 2
    4.40 +#define CPUID_REG_ECX 3
    4.41 +#define CPUID_REG_EDX 4
    4.42 +
    4.43 +/* mapping CPUID features to names
    4.44 + * holds a "name" for each feature, specified by the "leaf" number (and an
    4.45 + * optional "subleaf" in ECX), the "reg"ister (EAX-EDX) used and a number of
    4.46 + * bits starting with "bit" and being "length" bits long.
    4.47 + * Used for the static structure describing all features.
    4.48 + */
    4.49 +struct cpuid_flags {
    4.50 +    char* name;
    4.51 +    uint32_t leaf;
    4.52 +    uint32_t subleaf;
    4.53 +    int reg;
    4.54 +    int bit;
    4.55 +    int length;
    4.56 +};
    4.57 +
    4.58 +/* go through the dynamic array finding the entry for a specified leaf.
    4.59 + * if no entry exists, allocate one and return that.
    4.60 + */
    4.61 +static libxl_cpuid_policy_list cpuid_find_match(libxl_cpuid_policy_list *list,
    4.62 +                                          uint32_t leaf, uint32_t subleaf)
    4.63 +{
    4.64 +    int i = 0;
    4.65 +
    4.66 +    if (*list != NULL) {
    4.67 +        for (i = 0; (*list)[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
    4.68 +            if ((*list)[i].input[0] == leaf && (*list)[i].input[1] == subleaf)
    4.69 +                return *list + i;
    4.70 +        }
    4.71 +    }
    4.72 +    *list = realloc(*list, sizeof((*list)[0]) * (i + 2));
    4.73 +    (*list)[i].input[0] = leaf;
    4.74 +    (*list)[i].input[1] = subleaf;
    4.75 +    memset((*list)[i].policy, 0, 4 * sizeof(char*));
    4.76 +    (*list)[i + 1].input[0] = XEN_CPUID_INPUT_UNUSED;
    4.77 +    return *list + i;
    4.78 +}
    4.79 +
    4.80 +/* parse a single key=value pair and translate it into the libxc
    4.81 + * used interface using 32-characters strings for each register.
    4.82 + * Will overwrite earlier entries and thus can be called multiple
    4.83 + * times.
    4.84 + */
    4.85 +int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
    4.86 +{
    4.87 +#define NA XEN_CPUID_INPUT_UNUSED
    4.88 +    struct cpuid_flags cpuid_flags[] = {
    4.89 +        {"maxleaf",      0x00000000, NA, CPUID_REG_EAX,  0, 32},
    4.90 +      /* the following two entries are subject to tweaking later in the code */
    4.91 +        {"family",       0x00000001, NA, CPUID_REG_EAX,  8,  8},
    4.92 +        {"model",        0x00000001, NA, CPUID_REG_EAX,  4,  8},
    4.93 +        {"stepping",     0x00000001, NA, CPUID_REG_EAX,  0,  4},
    4.94 +        {"localapicid",  0x00000001, NA, CPUID_REG_EBX, 24,  8},
    4.95 +        {"proccount",    0x00000001, NA, CPUID_REG_EBX, 16,  8},
    4.96 +        {"clflush",      0x00000001, NA, CPUID_REG_EBX,  8,  8},
    4.97 +        {"brandid",      0x00000001, NA, CPUID_REG_EBX,  0,  8},
    4.98 +        {"f16c",         0x00000001, NA, CPUID_REG_ECX, 29,  1},
    4.99 +        {"avx",          0x00000001, NA, CPUID_REG_ECX, 28,  1},
   4.100 +        {"osxsave",      0x00000001, NA, CPUID_REG_ECX, 27,  1},
   4.101 +        {"xsave",        0x00000001, NA, CPUID_REG_ECX, 26,  1},
   4.102 +        {"aes",          0x00000001, NA, CPUID_REG_ECX, 25,  1},
   4.103 +        {"popcnt",       0x00000001, NA, CPUID_REG_ECX, 23,  1},
   4.104 +        {"movbe",        0x00000001, NA, CPUID_REG_ECX, 22,  1},
   4.105 +        {"x2apic",       0x00000001, NA, CPUID_REG_ECX, 21,  1},
   4.106 +        {"sse4.2",       0x00000001, NA, CPUID_REG_ECX, 20,  1},
   4.107 +        {"sse4.1",       0x00000001, NA, CPUID_REG_ECX, 19,  1},
   4.108 +        {"dca",          0x00000001, NA, CPUID_REG_ECX, 18,  1},
   4.109 +        {"pdcm",         0x00000001, NA, CPUID_REG_ECX, 15,  1},
   4.110 +        {"xtpr",         0x00000001, NA, CPUID_REG_ECX, 14,  1},
   4.111 +        {"cmpxchg16",    0x00000001, NA, CPUID_REG_ECX, 13,  1},
   4.112 +        {"cntxid",       0x00000001, NA, CPUID_REG_ECX, 10,  1},
   4.113 +        {"ssse3",        0x00000001, NA, CPUID_REG_ECX,  9,  1},
   4.114 +        {"tm2",          0x00000001, NA, CPUID_REG_ECX,  8,  1},
   4.115 +        {"est",          0x00000001, NA, CPUID_REG_ECX,  7,  1},
   4.116 +        {"smx",          0x00000001, NA, CPUID_REG_ECX,  6,  1},
   4.117 +        {"vmx",          0x00000001, NA, CPUID_REG_ECX,  5,  1},
   4.118 +        {"dscpl",        0x00000001, NA, CPUID_REG_ECX,  4,  1},
   4.119 +        {"monitor",      0x00000001, NA, CPUID_REG_ECX,  3,  1},
   4.120 +        {"dtes64",       0x00000001, NA, CPUID_REG_ECX,  2,  1},
   4.121 +        {"sse3",         0x00000001, NA, CPUID_REG_ECX,  0,  1},
   4.122 +        {"pbe",          0x00000001, NA, CPUID_REG_EDX, 31,  1},
   4.123 +        {"ia64",         0x00000001, NA, CPUID_REG_EDX, 30,  1},
   4.124 +        {"tm",           0x00000001, NA, CPUID_REG_EDX, 29,  1},
   4.125 +        {"htt",          0x00000001, NA, CPUID_REG_EDX, 28,  1},
   4.126 +        {"ss",           0x00000001, NA, CPUID_REG_EDX, 27,  1},
   4.127 +        {"sse2",         0x00000001, NA, CPUID_REG_EDX, 26,  1},
   4.128 +        {"sse",          0x00000001, NA, CPUID_REG_EDX, 25,  1},
   4.129 +        {"fxsr",         0x00000001, NA, CPUID_REG_EDX, 24,  1},
   4.130 +        {"mmx",          0x00000001, NA, CPUID_REG_EDX, 23,  1},
   4.131 +        {"acpi",         0x00000001, NA, CPUID_REG_EDX, 22,  1},
   4.132 +        {"ds",           0x00000001, NA, CPUID_REG_EDX, 21,  1},
   4.133 +        {"clfsh",        0x00000001, NA, CPUID_REG_EDX, 19,  1},
   4.134 +        {"psn",          0x00000001, NA, CPUID_REG_EDX, 18,  1},
   4.135 +        {"pse36",        0x00000001, NA, CPUID_REG_EDX, 17,  1},
   4.136 +        {"pat",          0x00000001, NA, CPUID_REG_EDX, 16,  1},
   4.137 +        {"cmov",         0x00000001, NA, CPUID_REG_EDX, 15,  1},
   4.138 +        {"mca",          0x00000001, NA, CPUID_REG_EDX, 14,  1},
   4.139 +        {"pge",          0x00000001, NA, CPUID_REG_EDX, 13,  1},
   4.140 +        {"mtrr",         0x00000001, NA, CPUID_REG_EDX, 12,  1},
   4.141 +        {"sysenter",     0x00000001, NA, CPUID_REG_EDX, 11,  1},
   4.142 +        {"apic",         0x00000001, NA, CPUID_REG_EDX,  9,  1},
   4.143 +        {"cmpxchg8",     0x00000001, NA, CPUID_REG_EDX,  8,  1},
   4.144 +        {"mce",          0x00000001, NA, CPUID_REG_EDX,  7,  1},
   4.145 +        {"pae",          0x00000001, NA, CPUID_REG_EDX,  6,  1},
   4.146 +        {"msr",          0x00000001, NA, CPUID_REG_EDX,  5,  1},
   4.147 +        {"tsc",          0x00000001, NA, CPUID_REG_EDX,  4,  1},
   4.148 +        {"pse",          0x00000001, NA, CPUID_REG_EDX,  3,  1},
   4.149 +        {"de",           0x00000001, NA, CPUID_REG_EDX,  2,  1},
   4.150 +        {"vme",          0x00000001, NA, CPUID_REG_EDX,  1,  1},
   4.151 +        {"fpu",          0x00000001, NA, CPUID_REG_EDX,  0,  1},
   4.152 +        {"topoext",      0x80000001, NA, CPUID_REG_ECX, 22,  1},
   4.153 +        {"tbm",          0x80000001, NA, CPUID_REG_ECX, 21,  1},
   4.154 +        {"nodeid",       0x80000001, NA, CPUID_REG_ECX, 19,  1},
   4.155 +        {"fma4",         0x80000001, NA, CPUID_REG_ECX, 16,  1},
   4.156 +        {"lwp",          0x80000001, NA, CPUID_REG_ECX, 15,  1},
   4.157 +        {"wdt",          0x80000001, NA, CPUID_REG_ECX, 13,  1},
   4.158 +        {"skinit",       0x80000001, NA, CPUID_REG_ECX, 12,  1},
   4.159 +        {"xop",          0x80000001, NA, CPUID_REG_ECX, 11,  1},
   4.160 +        {"ibs",          0x80000001, NA, CPUID_REG_ECX, 10,  1},
   4.161 +        {"osvw",         0x80000001, NA, CPUID_REG_ECX, 10,  1},
   4.162 +        {"3dnowprefetch",0x80000001, NA, CPUID_REG_ECX,  8,  1},
   4.163 +        {"misalignsse",  0x80000001, NA, CPUID_REG_ECX,  7,  1},
   4.164 +        {"sse4a",        0x80000001, NA, CPUID_REG_ECX,  6,  1},
   4.165 +        {"abm",          0x80000001, NA, CPUID_REG_ECX,  5,  1},
   4.166 +        {"altmovcr8",    0x80000001, NA, CPUID_REG_ECX,  4,  1},
   4.167 +        {"extapic",      0x80000001, NA, CPUID_REG_ECX,  3,  1},
   4.168 +        {"svm",          0x80000001, NA, CPUID_REG_ECX,  2,  1},
   4.169 +        {"cmplegacy",    0x80000001, NA, CPUID_REG_ECX,  1,  1},
   4.170 +        {"lahfsahf",     0x80000001, NA, CPUID_REG_ECX,  0,  1},
   4.171 +        {"3dnow",        0x80000001, NA, CPUID_REG_EDX, 31,  1},
   4.172 +        {"3dnowext",     0x80000001, NA, CPUID_REG_EDX, 30,  1},
   4.173 +        {"lm",           0x80000001, NA, CPUID_REG_EDX, 29,  1},
   4.174 +        {"rdtscp",       0x80000001, NA, CPUID_REG_EDX, 27,  1},
   4.175 +        {"page1gb",      0x80000001, NA, CPUID_REG_EDX, 26,  1},
   4.176 +        {"ffxsr",        0x80000001, NA, CPUID_REG_EDX, 25,  1},
   4.177 +        {"mmxext",       0x80000001, NA, CPUID_REG_EDX, 22,  1},
   4.178 +        {"nx",           0x80000001, NA, CPUID_REG_EDX, 20,  1},
   4.179 +        {"syscall",      0x80000001, NA, CPUID_REG_EDX, 11,  1},
   4.180 +        {"procpkg",      0x00000004,  0, CPUID_REG_EAX, 26,  6},
   4.181 +        {"apicidsize",   0x80000008, NA, CPUID_REG_ECX, 12,  4},
   4.182 +        {"nc",           0x80000008, NA, CPUID_REG_ECX,  0,  8},
   4.183 +
   4.184 +        {NULL, 0, CPUID_REG_INV, 0, 0}
   4.185 +    };
   4.186 +#undef NA
   4.187 +    char *sep, *val, *endptr;
   4.188 +    int i;
   4.189 +    struct cpuid_flags *flag;
   4.190 +    struct libxl__cpuid_policy *entry;
   4.191 +    unsigned long num;
   4.192 +    char flags[33], *resstr;
   4.193 +
   4.194 +    sep = strchr(str, '=');
   4.195 +    if (sep == NULL) {
   4.196 +        return 1;
   4.197 +    } else {
   4.198 +        val = sep + 1;
   4.199 +    }
   4.200 +    for (flag = cpuid_flags; flag->name != NULL; flag++) {
   4.201 +        if(!strncmp(str, flag->name, sep - str) && flag->name[sep - str] == 0)
   4.202 +            break;
   4.203 +    }
   4.204 +    if (flag->name == NULL) {
   4.205 +        return 2;
   4.206 +    }
   4.207 +    entry = cpuid_find_match(cpuid, flag->leaf, flag->subleaf);
   4.208 +    resstr = entry->policy[flag->reg - 1];
   4.209 +    if (resstr == NULL) {
   4.210 +        resstr = strdup("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
   4.211 +    }
   4.212 +    num = strtoull(val, &endptr, 0);
   4.213 +    flags[flag->length] = 0;
   4.214 +    if (endptr != val) {
   4.215 +        /* is this was a valid number, write the binary form into the string */
   4.216 +        for (i = 0; i < flag->length; i++) {
   4.217 +            flags[flag->length - 1 - i] = "01"[!!(num & (1 << i))];
   4.218 +        }
   4.219 +    } else {
   4.220 +        switch(val[0]) {
   4.221 +        case 'x': case 'k': case 's':
   4.222 +            memset(flags, val[0], flag->length);
   4.223 +            break;
   4.224 +        default:
   4.225 +            return 3;
   4.226 +        }
   4.227 +    }
   4.228 +    /* the family and model entry is potentially split up across
   4.229 +     * two fields in Fn0000_0001_EAX, so handle them here separately.
   4.230 +     */
   4.231 +    if (!strncmp(str, "family", sep - str)) {
   4.232 +        if (num < 16) {
   4.233 +            memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
   4.234 +            memcpy(resstr + (32 - 8) - 20, "00000000", 8);
   4.235 +        } else {
   4.236 +            num -= 15;
   4.237 +            memcpy(resstr + (32 - 4) - flag->bit, "1111", 4);
   4.238 +            for (i = 0; i < 7; i++) {
   4.239 +                flags[7 - i] = "01"[num & 1];
   4.240 +                num >>= 1;
   4.241 +            }
   4.242 +            memcpy(resstr + (32 - 8) - 20, flags, 8);
   4.243 +        }
   4.244 +    } else if (!strncmp(str, "model", sep - str)) {
   4.245 +        memcpy(resstr + (32 - 4) - 16, flags, 4);
   4.246 +        memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
   4.247 +    } else {
   4.248 +        memcpy(resstr + (32 - flag->length) - flag->bit, flags,
   4.249 +               flag->length);
   4.250 +    }
   4.251 +    entry->policy[flag->reg - 1] = resstr;
   4.252 +
   4.253 +    return 0;
   4.254 +}
   4.255 +
   4.256 +/* parse a single list item from the legacy Python xend syntax, where
   4.257 + * the strings for each register were directly exposed to the user.
   4.258 + * Used for maintaining compatibility with older config files
   4.259 + */
   4.260 +int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
   4.261 +                                  const char* str)
   4.262 +{
   4.263 +    char *endptr;
   4.264 +    unsigned long value;
   4.265 +    uint32_t leaf, subleaf = XEN_CPUID_INPUT_UNUSED;
   4.266 +    struct libxl__cpuid_policy *entry;
   4.267 +
   4.268 +    /* parse the leaf number */
   4.269 +    value = strtoul(str, &endptr, 0);
   4.270 +    if (str == endptr) {
   4.271 +        return 1;
   4.272 +    }
   4.273 +    leaf = value;
   4.274 +    /* check for an optional subleaf number */
   4.275 +    if (*endptr == ',') {
   4.276 +        str = endptr + 1;
   4.277 +        value = strtoul(str, &endptr, 0);
   4.278 +        if (str == endptr) {
   4.279 +            return 2;
   4.280 +        }
   4.281 +        subleaf = value;
   4.282 +    }
   4.283 +    if (*endptr != ':') {
   4.284 +        return 3;
   4.285 +    }
   4.286 +    str = endptr + 1;
   4.287 +    entry = cpuid_find_match(cpuid, leaf, subleaf);
   4.288 +    for (str = endptr + 1; *str != 0;) {
   4.289 +        if (str[0] != 'e' || str[2] != 'x') {
   4.290 +            return 4;
   4.291 +        }
   4.292 +        value = str[1] - 'a';
   4.293 +        endptr = strchr(str, '=');
   4.294 +        if (value < 0 || value > 3 || endptr == NULL) {
   4.295 +            return 4;
   4.296 +        }
   4.297 +        str = endptr + 1;
   4.298 +        endptr = strchr(str, ',');
   4.299 +        if (endptr == NULL) {
   4.300 +            endptr = strchr(str, 0);
   4.301 +        }
   4.302 +        if (endptr - str != 32) {
   4.303 +            return 5;
   4.304 +        }
   4.305 +        entry->policy[value] = calloc(32 + 1, 1);
   4.306 +        strncpy(entry->policy[value], str, 32);
   4.307 +        entry->policy[value][32] = 0;
   4.308 +        if (*endptr == 0) {
   4.309 +            break;
   4.310 +        }
   4.311 +        for (str = endptr + 1; *str == ' ' || *str == '\n'; str++);
   4.312 +    }
   4.313 +    return 0;
   4.314 +}
   4.315 +
   4.316 +void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid)
   4.317 +{
   4.318 +    xc_cpuid_apply_policy(ctx->xch, domid);
   4.319 +}
   4.320 +
   4.321 +void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
   4.322 +		     libxl_cpuid_policy_list cpuid)
   4.323 +{
   4.324 +    int i;
   4.325 +    char *cpuid_res[4];
   4.326 +
   4.327 +    for (i = 0; cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++)
   4.328 +        xc_cpuid_set(ctx->xch, domid, cpuid[i].input,
   4.329 +                     (const char**)(cpuid[i].policy), cpuid_res);
   4.330 +}
     5.1 --- a/tools/libxl/libxl_dom.c	Tue Nov 09 12:00:05 2010 +0000
     5.2 +++ b/tools/libxl/libxl_dom.c	Tue Nov 09 17:43:12 2010 +0000
     5.3 @@ -96,16 +96,10 @@ int libxl__build_post(libxl_ctx *ctx, ui
     5.4      xs_transaction_t t;
     5.5      char **ents;
     5.6      int i;
     5.7 -    char *cpuid_res[4];
     5.8  
     5.9 -#if defined(__i386__) || defined(__x86_64__)
    5.10 -    xc_cpuid_apply_policy(ctx->xch, domid);
    5.11 -    if (info->cpuid != NULL) {
    5.12 -        for (i = 0; info->cpuid[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++)
    5.13 -            xc_cpuid_set(ctx->xch, domid, info->cpuid[i].input,
    5.14 -                         (const char**)(info->cpuid[i].policy), cpuid_res);
    5.15 -    }
    5.16 -#endif
    5.17 +    libxl_cpuid_apply_policy(ctx, domid);
    5.18 +    if (info->cpuid != NULL)
    5.19 +        libxl_cpuid_set(ctx, domid, info->cpuid);
    5.20  
    5.21      ents = libxl__calloc(&gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
    5.22      ents[0] = "memory/static-max";
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libxl/libxl_nocpuid.c	Tue Nov 09 17:43:12 2010 +0000
     6.3 @@ -0,0 +1,37 @@
     6.4 +/*
     6.5 + * This program is free software; you can redistribute it and/or modify
     6.6 + * it under the terms of the GNU Lesser General Public License as published
     6.7 + * by the Free Software Foundation; version 2.1 only. with the special
     6.8 + * exception on linking described in file LICENSE.
     6.9 + *
    6.10 + * This program is distributed in the hope that it will be useful,
    6.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.13 + * GNU Lesser General Public License for more details.
    6.14 + */
    6.15 +
    6.16 +#include "libxl.h"
    6.17 +
    6.18 +void libxl_cpuid_destroy(libxl_cpuid_policy_list *p_cpuid_list)
    6.19 +{
    6.20 +}
    6.21 +
    6.22 +int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
    6.23 +{
    6.24 +    return 0;
    6.25 +}
    6.26 +
    6.27 +int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
    6.28 +                                  const char* str)
    6.29 +{
    6.30 +    return 0;
    6.31 +}
    6.32 +
    6.33 +void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid)
    6.34 +{
    6.35 +}
    6.36 +
    6.37 +void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
    6.38 +		     libxl_cpuid_policy_list cpuid)
    6.39 +{
    6.40 +}