xref: /kvmtool/powerpc/cpu_info.c (revision d391177a7181c1ca48b76f4905740079e0226e4e)
1*d391177aSMatt Evans /*
2*d391177aSMatt Evans  * PPC CPU identification
3*d391177aSMatt Evans  *
4*d391177aSMatt Evans  * This is a very simple "host CPU info" struct to get us going.
5*d391177aSMatt Evans  * For the little host information we need, I don't want to grub about
6*d391177aSMatt Evans  * parsing stuff in /proc/device-tree so just match host PVR to differentiate
7*d391177aSMatt Evans  * PPC970 and POWER7 (which is all that's currently supported).
8*d391177aSMatt Evans  *
9*d391177aSMatt Evans  * Qemu does something similar but this is MUCH simpler!
10*d391177aSMatt Evans  *
11*d391177aSMatt Evans  * Copyright 2012 Matt Evans <matt@ozlabs.org>, IBM Corporation.
12*d391177aSMatt Evans  *
13*d391177aSMatt Evans  * This program is free software; you can redistribute it and/or modify it
14*d391177aSMatt Evans  * under the terms of the GNU General Public License version 2 as published
15*d391177aSMatt Evans  * by the Free Software Foundation.
16*d391177aSMatt Evans  */
17*d391177aSMatt Evans 
18*d391177aSMatt Evans #include "cpu_info.h"
19*d391177aSMatt Evans #include "kvm/util.h"
20*d391177aSMatt Evans 
21*d391177aSMatt Evans /* POWER7 */
22*d391177aSMatt Evans 
23*d391177aSMatt Evans /*
24*d391177aSMatt Evans  * Basic set of pages for POWER7.  It actually supports more but there were some
25*d391177aSMatt Evans  * limitations as to which may be advertised to the guest.  FIXME when this
26*d391177aSMatt Evans  * settles down -- for now use basic set:
27*d391177aSMatt Evans  */
28*d391177aSMatt Evans static u32 power7_page_sizes_prop[] = {0xc, 0x0, 0x1, 0xc, 0x0, 0x18, 0x100, 0x1, 0x18, 0x0};
29*d391177aSMatt Evans /* POWER7 has 1T segments, so advertise these */
30*d391177aSMatt Evans static u32 power7_segment_sizes_prop[] = {0x1c, 0x28, 0xffffffff, 0xffffffff};
31*d391177aSMatt Evans 
32*d391177aSMatt Evans static struct cpu_info cpu_power7_info = {
33*d391177aSMatt Evans 	"POWER7",
34*d391177aSMatt Evans 	power7_page_sizes_prop, sizeof(power7_page_sizes_prop),
35*d391177aSMatt Evans 	power7_segment_sizes_prop, sizeof(power7_segment_sizes_prop),
36*d391177aSMatt Evans 	32, 		/* SLB size */
37*d391177aSMatt Evans 	512000000, 	/* TB frequency */
38*d391177aSMatt Evans 	128,		/* d-cache block size */
39*d391177aSMatt Evans 	128,		/* i-cache block size */
40*d391177aSMatt Evans 	CPUINFO_FLAG_DFP | CPUINFO_FLAG_VSX | CPUINFO_FLAG_VMX
41*d391177aSMatt Evans };
42*d391177aSMatt Evans 
43*d391177aSMatt Evans /* PPC970/G5 */
44*d391177aSMatt Evans 
45*d391177aSMatt Evans static u32 g5_page_sizes_prop[] = {0xc, 0x0, 0x1, 0xc, 0x0, 0x18, 0x100, 0x1, 0x18, 0x0};
46*d391177aSMatt Evans 
47*d391177aSMatt Evans static struct cpu_info cpu_970_info = {
48*d391177aSMatt Evans 	"G5",
49*d391177aSMatt Evans 	g5_page_sizes_prop, sizeof(g5_page_sizes_prop),
50*d391177aSMatt Evans 	0 /* Null = no segment sizes prop, use defaults */, 0,
51*d391177aSMatt Evans 	0, 		/* SLB size default */
52*d391177aSMatt Evans 	33333333, 	/* TB frequency */
53*d391177aSMatt Evans 	128,		/* d-cache block size */
54*d391177aSMatt Evans 	128,		/* i-cache block size */
55*d391177aSMatt Evans 	CPUINFO_FLAG_VMX
56*d391177aSMatt Evans };
57*d391177aSMatt Evans 
58*d391177aSMatt Evans /* This is a default catchall for 'no match' on PVR: */
59*d391177aSMatt Evans static struct cpu_info cpu_dummy_info = { "unknown", 0, 0, 0, 0, 0, 0, 0, 0 };
60*d391177aSMatt Evans 
61*d391177aSMatt Evans static struct pvr_info host_pvr_info[] = {
62*d391177aSMatt Evans 	{ 0xffffffff, 0x0f000003, &cpu_power7_info },
63*d391177aSMatt Evans 	{ 0xffff0000, 0x003f0000, &cpu_power7_info },
64*d391177aSMatt Evans 	{ 0xffff0000, 0x004a0000, &cpu_power7_info },
65*d391177aSMatt Evans 	{ 0xffff0000, 0x00390000, &cpu_970_info },
66*d391177aSMatt Evans 	{ 0xffff0000, 0x003c0000, &cpu_970_info },
67*d391177aSMatt Evans         { 0xffff0000, 0x00440000, &cpu_970_info },
68*d391177aSMatt Evans         { 0xffff0000, 0x00450000, &cpu_970_info },
69*d391177aSMatt Evans };
70*d391177aSMatt Evans 
71*d391177aSMatt Evans struct cpu_info *find_cpu_info(u32 pvr)
72*d391177aSMatt Evans {
73*d391177aSMatt Evans 	unsigned int i;
74*d391177aSMatt Evans 	for (i = 0; i < sizeof(host_pvr_info)/sizeof(struct pvr_info); i++) {
75*d391177aSMatt Evans 		if ((pvr & host_pvr_info[i].pvr_mask) ==
76*d391177aSMatt Evans 		    host_pvr_info[i].pvr) {
77*d391177aSMatt Evans 			return host_pvr_info[i].cpu_info;
78*d391177aSMatt Evans 		}
79*d391177aSMatt Evans 	}
80*d391177aSMatt Evans 	/* Didn't find anything? Rut-ro. */
81*d391177aSMatt Evans 	pr_warning("Host CPU unsupported by kvmtool\n");
82*d391177aSMatt Evans 	return &cpu_dummy_info;
83*d391177aSMatt Evans }
84