~ubuntu-branches/ubuntu/raring/libvirt/raring

« back to all changes in this revision

Viewing changes to src/cpu/cpu_powerpc.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-11-19 10:41:02 UTC
  • mfrom: (1.2.15) (223.1.2 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20121119104102-l6ewdppikysbzztu
Tags: 1.0.0-0ubuntu2
debian/patches/add-armhf-sysinfo-infomration.patch: Disable
to fix FTBFS on arm.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * cpu_powerpc.h: CPU driver for PowerPC CPUs
 
2
 * cpu_powerpc.c: CPU driver for PowerPC CPUs
3
3
 *
4
 
 * Copyright (C) Copyright (C) IBM Corporation, 2010
 
4
 * Copyright (C) IBM Corporation, 2010
5
5
 *
6
6
 * This library is free software; you can redistribute it and/or
7
7
 * modify it under the terms of the GNU Lesser General Public
14
14
 * Lesser General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
17
 * License along with this library.  If not, see
 
18
 * <http://www.gnu.org/licenses/>.
19
19
 *
20
20
 * Authors:
21
21
 *      Anton Blanchard <anton@au.ibm.com>
22
22
 *      Prerna Saxena <prerna@linux.vnet.ibm.com>
 
23
 *      Li Zhang <zhlcindy@linux.vnet.ibm.com>
23
24
 */
24
25
 
25
26
#include <config.h>
 
27
#include <stdint.h>
26
28
 
 
29
#include "logging.h"
27
30
#include "memory.h"
 
31
#include "util.h"
28
32
#include "cpu.h"
29
33
 
 
34
#include "cpu_map.h"
 
35
#include "buf.h"
30
36
 
31
37
#define VIR_FROM_THIS VIR_FROM_CPU
32
38
 
33
39
static const char *archs[] = { "ppc64" };
34
40
 
 
41
struct cpuPowerPC {
 
42
    const char *name;
 
43
    const char *vendor;
 
44
    uint32_t pvr;
 
45
};
 
46
 
 
47
static const struct cpuPowerPC cpu_defs[] = {
 
48
    {"POWER7", "IBM", 0x003f0200},
 
49
    {"POWER7_v2.1", "IBM", 0x003f0201},
 
50
    {"POWER7_v2.3", "IBM", 0x003f0203},
 
51
    {NULL, NULL, 0xffffffff}
 
52
};
 
53
 
 
54
 
 
55
struct ppc_vendor {
 
56
    char *name;
 
57
    struct ppc_vendor *next;
 
58
};
 
59
 
 
60
struct ppc_model {
 
61
    char *name;
 
62
    const struct ppc_vendor *vendor;
 
63
    union cpuData *data;
 
64
    struct ppc_model *next;
 
65
};
 
66
 
 
67
struct ppc_map {
 
68
    struct ppc_vendor *vendors;
 
69
    struct ppc_model *models;
 
70
};
 
71
 
 
72
static int
 
73
ConvertModelVendorFromPVR(char ***model,
 
74
                          char ***vendor,
 
75
                          uint32_t pvr)
 
76
{
 
77
    int i;
 
78
 
 
79
    for (i = 0; cpu_defs[i].name; i++) {
 
80
        if (cpu_defs[i].pvr == pvr) {
 
81
            **model = strdup(cpu_defs[i].name);
 
82
            **vendor = strdup(cpu_defs[i].vendor);
 
83
            return 0;
 
84
        }
 
85
    }
 
86
 
 
87
    virReportError(VIR_ERR_INTERNAL_ERROR,
 
88
                   "%s", _("Missing the definition of this model"));
 
89
    return -1;
 
90
}
 
91
 
 
92
static int
 
93
ConvertPVRFromModel(const char *model,
 
94
                    uint32_t *pvr)
 
95
{
 
96
    int i;
 
97
 
 
98
    for (i = 0; cpu_defs[i].name; i++) {
 
99
        if (STREQ(cpu_defs[i].name, model)) {
 
100
            *pvr = cpu_defs[i].pvr;
 
101
            return 0;
 
102
        }
 
103
    }
 
104
 
 
105
    virReportError(VIR_ERR_INTERNAL_ERROR,
 
106
                   "%s", _("Missing the definition of this model"));
 
107
    return -1;
 
108
}
 
109
 
 
110
static int
 
111
cpuMatch(const union cpuData *data,
 
112
         char **cpu_model,
 
113
         char **cpu_vendor,
 
114
         const struct ppc_model *model)
 
115
{
 
116
    int ret = 0;
 
117
 
 
118
    ret = ConvertModelVendorFromPVR(&cpu_model, &cpu_vendor, data->ppc.pvr);
 
119
 
 
120
    if (STREQ(model->name, *cpu_model) &&
 
121
        STREQ(model->vendor->name, *cpu_vendor))
 
122
        ret = 1;
 
123
 
 
124
    return ret;
 
125
}
 
126
 
 
127
 
 
128
static struct ppc_model *
 
129
ppcModelNew(void)
 
130
{
 
131
    struct ppc_model *model;
 
132
 
 
133
    if (VIR_ALLOC(model) < 0)
 
134
        return NULL;
 
135
 
 
136
    if (VIR_ALLOC(model->data) < 0) {
 
137
        VIR_FREE(model);
 
138
        return NULL;
 
139
    }
 
140
 
 
141
    return model;
 
142
}
 
143
 
 
144
static void
 
145
ppcModelFree(struct ppc_model *model)
 
146
{
 
147
    if (model == NULL)
 
148
        return;
 
149
 
 
150
    VIR_FREE(model->name);
 
151
 
 
152
    VIR_FREE(model->data);
 
153
 
 
154
    VIR_FREE(model);
 
155
}
 
156
 
 
157
static struct ppc_model *
 
158
ppcModelFind(const struct ppc_map *map,
 
159
             const char *name)
 
160
{
 
161
    struct ppc_model *model;
 
162
 
 
163
    model = map->models;
 
164
    while (model != NULL) {
 
165
        if (STREQ(model->name, name))
 
166
            return model;
 
167
 
 
168
        model = model->next;
 
169
    }
 
170
 
 
171
    return NULL;
 
172
}
 
173
 
 
174
static struct ppc_vendor *
 
175
ppcVendorFind(const struct ppc_map *map,
 
176
              const char *name)
 
177
{
 
178
    struct ppc_vendor *vendor;
 
179
 
 
180
    vendor = map->vendors;
 
181
    while (vendor) {
 
182
        if (STREQ(vendor->name, name))
 
183
            return vendor;
 
184
 
 
185
        vendor = vendor->next;
 
186
    }
 
187
 
 
188
    return NULL;
 
189
}
 
190
 
 
191
static void
 
192
ppcVendorFree(struct ppc_vendor *vendor)
 
193
{
 
194
    if (!vendor)
 
195
        return;
 
196
 
 
197
    VIR_FREE(vendor->name);
 
198
    VIR_FREE(vendor);
 
199
}
 
200
 
 
201
static int
 
202
ppcVendorLoad(xmlXPathContextPtr ctxt,
 
203
              struct ppc_map *map)
 
204
{
 
205
    struct ppc_vendor *vendor = NULL;
 
206
    char *string = NULL;
 
207
    int ret = -1;
 
208
 
 
209
    if (VIR_ALLOC(vendor) < 0)
 
210
        goto no_memory;
 
211
 
 
212
    vendor->name = virXPathString("string(@name)", ctxt);
 
213
    if (!vendor->name) {
 
214
        virReportError(VIR_ERR_INTERNAL_ERROR,
 
215
                       "%s", _("Missing CPU vendor name"));
 
216
        goto ignore;
 
217
    }
 
218
 
 
219
    if (ppcVendorFind(map, vendor->name)) {
 
220
        virReportError(VIR_ERR_INTERNAL_ERROR,
 
221
                       _("CPU vendor %s already defined"), vendor->name);
 
222
        goto ignore;
 
223
    }
 
224
 
 
225
    string = virXPathString("string(@string)", ctxt);
 
226
    if (!string) {
 
227
        virReportError(VIR_ERR_INTERNAL_ERROR,
 
228
                       _("Missing vendor string for CPU vendor %s"), vendor->name);
 
229
        goto ignore;
 
230
    }
 
231
    if (!map->vendors)
 
232
        map->vendors = vendor;
 
233
    else {
 
234
        vendor->next = map->vendors;
 
235
        map->vendors = vendor;
 
236
    }
 
237
 
 
238
    ret = 0;
 
239
 
 
240
out:
 
241
    VIR_FREE(string);
 
242
    return ret;
 
243
 
 
244
no_memory:
 
245
    virReportOOMError();
 
246
 
 
247
ignore:
 
248
    ppcVendorFree(vendor);
 
249
    goto out;
 
250
}
 
251
 
 
252
static int
 
253
ppcModelLoad(xmlXPathContextPtr ctxt,
 
254
             struct ppc_map *map)
 
255
{
 
256
    xmlNodePtr *nodes = NULL;
 
257
    struct ppc_model *model;
 
258
    char *vendor = NULL;
 
259
    int ret = -1;
 
260
 
 
261
    if (!(model = ppcModelNew()))
 
262
        goto no_memory;
 
263
 
 
264
    model->name = virXPathString("string(@name)", ctxt);
 
265
    if (model->name == NULL) {
 
266
        virReportError(VIR_ERR_INTERNAL_ERROR,
 
267
                       "%s", _("Missing CPU model name"));
 
268
        goto ignore;
 
269
    }
 
270
 
 
271
    ret = ConvertPVRFromModel(model->name, &model->data->ppc.pvr);
 
272
    if (ret < 0)
 
273
       goto ignore;
 
274
 
 
275
 
 
276
    if (virXPathBoolean("boolean(./vendor)", ctxt)) {
 
277
        vendor = virXPathString("string(./vendor/@name)", ctxt);
 
278
        if (!vendor) {
 
279
            virReportError(VIR_ERR_INTERNAL_ERROR,
 
280
                           _("Invalid vendor element in CPU model %s"),
 
281
                           model->name);
 
282
            goto ignore;
 
283
        }
 
284
 
 
285
        if (!(model->vendor = ppcVendorFind(map, vendor))) {
 
286
            virReportError(VIR_ERR_INTERNAL_ERROR,
 
287
                           _("Unknown vendor %s referenced by CPU model %s"),
 
288
                           vendor, model->name);
 
289
            goto ignore;
 
290
        }
 
291
    }
 
292
 
 
293
    if (map->models == NULL)
 
294
        map->models = model;
 
295
    else {
 
296
        model->next = map->models;
 
297
        map->models = model;
 
298
    }
 
299
 
 
300
    ret = 0;
 
301
 
 
302
out:
 
303
    VIR_FREE(vendor);
 
304
    VIR_FREE(nodes);
 
305
    return ret;
 
306
 
 
307
no_memory:
 
308
    virReportOOMError();
 
309
 
 
310
ignore:
 
311
    ppcModelFree(model);
 
312
    goto out;
 
313
}
 
314
 
 
315
static int
 
316
ppcMapLoadCallback(enum cpuMapElement element,
 
317
                   xmlXPathContextPtr ctxt,
 
318
                   void *data)
 
319
{
 
320
    struct ppc_map *map = data;
 
321
 
 
322
    switch (element) {
 
323
    case CPU_MAP_ELEMENT_VENDOR:
 
324
        return ppcVendorLoad(ctxt, map);
 
325
    case CPU_MAP_ELEMENT_MODEL:
 
326
        return ppcModelLoad(ctxt, map);
 
327
    default:
 
328
        break;
 
329
    }
 
330
 
 
331
    return 0;
 
332
}
 
333
 
 
334
static void
 
335
ppcMapFree(struct ppc_map *map)
 
336
{
 
337
    if (map == NULL)
 
338
        return;
 
339
 
 
340
    while (map->models != NULL) {
 
341
        struct ppc_model *model = map->models;
 
342
        map->models = model->next;
 
343
        ppcModelFree(model);
 
344
    }
 
345
 
 
346
    while (map->vendors != NULL) {
 
347
        struct ppc_vendor *vendor = map->vendors;
 
348
        map->vendors = vendor->next;
 
349
        ppcVendorFree(vendor);
 
350
    }
 
351
 
 
352
    VIR_FREE(map);
 
353
}
 
354
 
 
355
static struct ppc_map *
 
356
ppcLoadMap(void)
 
357
{
 
358
    struct ppc_map *map;
 
359
 
 
360
    if (VIR_ALLOC(map) < 0) {
 
361
        virReportOOMError();
 
362
        return NULL;
 
363
    }
 
364
 
 
365
    if (cpuMapLoad("ppc64", ppcMapLoadCallback, map) < 0)
 
366
        goto error;
 
367
 
 
368
    return map;
 
369
 
 
370
error:
 
371
    ppcMapFree(map);
 
372
    return NULL;
 
373
}
 
374
 
 
375
static struct ppc_model *
 
376
ppcModelCopy(const struct ppc_model *model)
 
377
{
 
378
    struct ppc_model *copy;
 
379
 
 
380
    if (VIR_ALLOC(copy) < 0
 
381
        || VIR_ALLOC(copy->data) < 0
 
382
        || !(copy->name = strdup(model->name))){
 
383
        ppcModelFree(copy);
 
384
        return NULL;
 
385
    }
 
386
 
 
387
    copy->data->ppc.pvr = model->data->ppc.pvr;
 
388
    copy->vendor = model->vendor;
 
389
 
 
390
    return copy;
 
391
}
 
392
 
 
393
static struct ppc_model *
 
394
ppcModelFromCPU(const virCPUDefPtr cpu,
 
395
                const struct ppc_map *map)
 
396
{
 
397
    struct ppc_model *model = NULL;
 
398
 
 
399
    if ((model = ppcModelFind(map, cpu->model))) {
 
400
        if ((model = ppcModelCopy(model)) == NULL) {
 
401
            goto no_memory;
 
402
        }
 
403
    } else if (!(model = ppcModelNew())) {
 
404
        goto no_memory;
 
405
    }
 
406
 
 
407
    return model;
 
408
 
 
409
no_memory:
 
410
    virReportOOMError();
 
411
    ppcModelFree(model);
 
412
 
 
413
    return NULL;
 
414
}
 
415
 
 
416
static virCPUCompareResult
 
417
PowerPCCompare(virCPUDefPtr host,
 
418
           virCPUDefPtr cpu)
 
419
{
 
420
    if ((cpu->arch && STRNEQ(host->arch, cpu->arch)) ||
 
421
        STRNEQ(host->model, cpu->model))
 
422
        return VIR_CPU_COMPARE_INCOMPATIBLE;
 
423
 
 
424
    return VIR_CPU_COMPARE_IDENTICAL;
 
425
}
 
426
 
 
427
static int
 
428
PowerPCDecode(virCPUDefPtr cpu,
 
429
          const union cpuData *data,
 
430
          const char **models,
 
431
          unsigned int nmodels,
 
432
          const char *preferred)
 
433
{
 
434
    int ret = -1;
 
435
    struct ppc_map *map;
 
436
    const struct ppc_model *candidate;
 
437
    virCPUDefPtr cpuCandidate;
 
438
    virCPUDefPtr cpuModel = NULL;
 
439
    char *cpu_vendor = NULL;
 
440
    char *cpu_model = NULL;
 
441
    unsigned int i;
 
442
 
 
443
    if (data == NULL || (map = ppcLoadMap()) == NULL)
 
444
        return -1;
 
445
 
 
446
    candidate = map->models;
 
447
 
 
448
    while (candidate != NULL) {
 
449
        bool allowed = (models == NULL);
 
450
 
 
451
        for (i = 0; i < nmodels; i++) {
 
452
            if (models && models[i] && STREQ(models[i], candidate->name)) {
 
453
                allowed = true;
 
454
                break;
 
455
            }
 
456
        }
 
457
 
 
458
        if (!allowed) {
 
459
            if (preferred && STREQ(candidate->name, preferred)) {
 
460
                if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) {
 
461
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
 
462
                                   _("CPU model %s is not supported by hypervisor"),
 
463
                                   preferred);
 
464
                    goto out;
 
465
                } else {
 
466
                    VIR_WARN("Preferred CPU model %s not allowed by"
 
467
                             " hypervisor; closest supported model will be"
 
468
                             " used", preferred);
 
469
                }
 
470
            } else {
 
471
                VIR_DEBUG("CPU model %s not allowed by hypervisor; ignoring",
 
472
                          candidate->name);
 
473
            }
 
474
            goto next;
 
475
        }
 
476
 
 
477
        if (VIR_ALLOC(cpuCandidate) < 0) {
 
478
            virReportOOMError();
 
479
            goto out;
 
480
        }
 
481
 
 
482
        cpuCandidate->model = strdup(candidate->name);
 
483
        cpuCandidate->vendor = strdup(candidate->vendor->name);
 
484
 
 
485
        if (preferred && STREQ(cpuCandidate->model, preferred)) {
 
486
            virCPUDefFree(cpuModel);
 
487
            cpuModel = cpuCandidate;
 
488
            break;
 
489
        }
 
490
 
 
491
        ret = cpuMatch(data, &cpu_model, &cpu_vendor, candidate);
 
492
        if (ret < 0) {
 
493
            VIR_FREE(cpuCandidate);
 
494
            goto out;
 
495
        }else if(ret == 1) {
 
496
            cpuCandidate->model = cpu_model;
 
497
            cpuCandidate->vendor = cpu_vendor;
 
498
            virCPUDefFree(cpuModel);
 
499
            cpuModel = cpuCandidate;
 
500
            break;
 
501
        }
 
502
 
 
503
        virCPUDefFree(cpuCandidate);
 
504
 
 
505
    next:
 
506
        candidate = candidate->next;
 
507
    }
 
508
 
 
509
    if (cpuModel == NULL) {
 
510
        virReportError(VIR_ERR_INTERNAL_ERROR,
 
511
                       "%s", _("Cannot find suitable CPU model for given data"));
 
512
        goto out;
 
513
    }
 
514
 
 
515
    cpu->model = cpuModel->model;
 
516
    cpu->vendor = cpuModel->vendor;
 
517
    VIR_FREE(cpuModel);
 
518
 
 
519
    ret = 0;
 
520
 
 
521
out:
 
522
    ppcMapFree(map);
 
523
    virCPUDefFree(cpuModel);
 
524
 
 
525
    return ret;
 
526
}
 
527
 
 
528
#if defined(__powerpc__) || \
 
529
    defined(__powerpc64__)
 
530
static uint32_t ppc_mfpvr(void)
 
531
{
 
532
    uint32_t pvr;
 
533
    asm ("mfpvr %0"
 
534
        : "=r"(pvr));
 
535
    return pvr;
 
536
}
 
537
#endif
 
538
 
 
539
static void
 
540
PowerPCDataFree(union cpuData *data)
 
541
{
 
542
    if (data == NULL)
 
543
        return;
 
544
 
 
545
    VIR_FREE(data);
 
546
}
 
547
 
35
548
static union cpuData *
36
549
PowerPCNodeData(void)
37
550
{
42
555
        return NULL;
43
556
    }
44
557
 
 
558
#if defined(__powerpc__) || \
 
559
    defined(__powerpc64__)
 
560
    data->ppc.pvr = ppc_mfpvr();
 
561
#endif
 
562
 
45
563
    return data;
46
564
}
47
565
 
48
 
 
49
566
static int
50
 
PowerPCDecode(virCPUDefPtr cpu ATTRIBUTE_UNUSED,
51
 
              const union cpuData *data ATTRIBUTE_UNUSED,
52
 
              const char **models ATTRIBUTE_UNUSED,
53
 
              unsigned int nmodels ATTRIBUTE_UNUSED,
54
 
              const char *preferred ATTRIBUTE_UNUSED)
 
567
PowerPCUpdate(virCPUDefPtr guest ATTRIBUTE_UNUSED,
 
568
          const virCPUDefPtr host ATTRIBUTE_UNUSED)
55
569
{
56
 
        return 0;
 
570
   return 0;
57
571
}
58
 
 
59
 
static void
60
 
PowerPCDataFree(union cpuData *data)
 
572
static virCPUDefPtr
 
573
PowerPCBaseline(virCPUDefPtr *cpus,
 
574
                unsigned int ncpus ATTRIBUTE_UNUSED,
 
575
                const char **models ATTRIBUTE_UNUSED,
 
576
                unsigned int nmodels ATTRIBUTE_UNUSED)
61
577
{
62
 
   if (data == NULL)
63
 
       return;
64
 
 
65
 
   VIR_FREE(data);
 
578
    struct ppc_map *map = NULL;
 
579
    struct ppc_model *base_model = NULL;
 
580
    virCPUDefPtr cpu = NULL;
 
581
    struct ppc_model *model = NULL;
 
582
    bool outputModel = true;
 
583
 
 
584
    if (!(map = ppcLoadMap())) {
 
585
        goto error;
 
586
    }
 
587
 
 
588
    if (!(base_model = ppcModelFromCPU(cpus[0], map))) {
 
589
        goto error;
 
590
    }
 
591
 
 
592
    if (VIR_ALLOC(cpu) < 0 ||
 
593
        !(cpu->arch = strdup(cpus[0]->arch)))
 
594
        goto no_memory;
 
595
    cpu->type = VIR_CPU_TYPE_GUEST;
 
596
    cpu->match = VIR_CPU_MATCH_EXACT;
 
597
 
 
598
    if (!cpus[0]->model) {
 
599
        outputModel = false;
 
600
    } else if (!(model = ppcModelFind(map, cpus[0]->model))) {
 
601
        virReportError(VIR_ERR_OPERATION_FAILED,
 
602
                       _("Unknown CPU vendor %s"), cpus[0]->model);
 
603
        goto error;
 
604
    }
 
605
 
 
606
    base_model->data->ppc.pvr = model->data->ppc.pvr;
 
607
    if (PowerPCDecode(cpu, base_model->data, models, nmodels, NULL) < 0)
 
608
        goto error;
 
609
 
 
610
    if (!outputModel)
 
611
        VIR_FREE(cpu->model);
 
612
 
 
613
    VIR_FREE(cpu->arch);
 
614
 
 
615
cleanup:
 
616
    ppcModelFree(base_model);
 
617
    ppcMapFree(map);
 
618
 
 
619
    return cpu;
 
620
no_memory:
 
621
    virReportOOMError();
 
622
error:
 
623
    ppcModelFree(model);
 
624
    virCPUDefFree(cpu);
 
625
    cpu = NULL;
 
626
    goto cleanup;
66
627
}
67
628
 
68
629
struct cpuArchDriver cpuDriverPowerPC = {
69
630
    .name = "ppc64",
70
631
    .arch = archs,
71
632
    .narch = ARRAY_CARDINALITY(archs),
72
 
    .compare    = NULL,
 
633
    .compare    = PowerPCCompare,
73
634
    .decode     = PowerPCDecode,
74
635
    .encode     = NULL,
75
636
    .free       = PowerPCDataFree,
76
637
    .nodeData   = PowerPCNodeData,
77
638
    .guestData  = NULL,
78
 
    .baseline   = NULL,
79
 
    .update     = NULL,
 
639
    .baseline   = PowerPCBaseline,
 
640
    .update     = PowerPCUpdate,
80
641
    .hasFeature = NULL,
81
642
};