xref: /kvmtool/powerpc/cpu_info.c (revision ac92dd434f648d5656bd49011248b3fcd52d16f5)
1d391177aSMatt Evans /*
2d391177aSMatt Evans  * PPC CPU identification
3d391177aSMatt Evans  *
4d391177aSMatt Evans  * This is a very simple "host CPU info" struct to get us going.
5d391177aSMatt Evans  * For the little host information we need, I don't want to grub about
6d391177aSMatt Evans  * parsing stuff in /proc/device-tree so just match host PVR to differentiate
7d391177aSMatt Evans  * PPC970 and POWER7 (which is all that's currently supported).
8d391177aSMatt Evans  *
9d391177aSMatt Evans  * Qemu does something similar but this is MUCH simpler!
10d391177aSMatt Evans  *
11d391177aSMatt Evans  * Copyright 2012 Matt Evans <matt@ozlabs.org>, IBM Corporation.
12d391177aSMatt Evans  *
13d391177aSMatt Evans  * This program is free software; you can redistribute it and/or modify it
14d391177aSMatt Evans  * under the terms of the GNU General Public License version 2 as published
15d391177aSMatt Evans  * by the Free Software Foundation.
16d391177aSMatt Evans  */
17d391177aSMatt Evans 
18d391177aSMatt Evans #include "cpu_info.h"
19d391177aSMatt Evans #include "kvm/util.h"
20d391177aSMatt Evans 
21d391177aSMatt Evans /* POWER7 */
22d391177aSMatt Evans 
23d391177aSMatt Evans /*
24d391177aSMatt Evans  * Basic set of pages for POWER7.  It actually supports more but there were some
25d391177aSMatt Evans  * limitations as to which may be advertised to the guest.  FIXME when this
26d391177aSMatt Evans  * settles down -- for now use basic set:
27d391177aSMatt Evans  */
28d391177aSMatt Evans static u32 power7_page_sizes_prop[] = {0xc, 0x0, 0x1, 0xc, 0x0, 0x18, 0x100, 0x1, 0x18, 0x0};
29d391177aSMatt Evans /* POWER7 has 1T segments, so advertise these */
30d391177aSMatt Evans static u32 power7_segment_sizes_prop[] = {0x1c, 0x28, 0xffffffff, 0xffffffff};
31d391177aSMatt Evans 
32d391177aSMatt Evans static struct cpu_info cpu_power7_info = {
3395477af3SMichael Ellerman 	.name = "POWER7",
3495477af3SMichael Ellerman 	.page_sizes_prop = power7_page_sizes_prop,
3595477af3SMichael Ellerman 	.page_sizes_prop_len = sizeof(power7_segment_sizes_prop),
3695477af3SMichael Ellerman 	.segment_sizes_prop = power7_segment_sizes_prop,
3795477af3SMichael Ellerman 	.segment_sizes_prop_len = sizeof(power7_segment_sizes_prop),
3895477af3SMichael Ellerman 	.slb_size = 32,
3995477af3SMichael Ellerman 	.tb_freq = 512000000,
4095477af3SMichael Ellerman 	.d_bsize = 128,
4195477af3SMichael Ellerman 	.i_bsize = 128,
4295477af3SMichael Ellerman 	.flags = CPUINFO_FLAG_DFP | CPUINFO_FLAG_VSX | CPUINFO_FLAG_VMX,
43d391177aSMatt Evans };
44d391177aSMatt Evans 
45d391177aSMatt Evans /* PPC970/G5 */
46d391177aSMatt Evans 
47d391177aSMatt Evans static u32 g5_page_sizes_prop[] = {0xc, 0x0, 0x1, 0xc, 0x0, 0x18, 0x100, 0x1, 0x18, 0x0};
48d391177aSMatt Evans 
49d391177aSMatt Evans static struct cpu_info cpu_970_info = {
5095477af3SMichael Ellerman 	.name = "G5",
5195477af3SMichael Ellerman 	.page_sizes_prop = g5_page_sizes_prop,
5295477af3SMichael Ellerman 	.page_sizes_prop_len = sizeof(g5_page_sizes_prop),
5395477af3SMichael Ellerman 	.segment_sizes_prop = NULL /* no segment sizes prop, use defaults */,
5495477af3SMichael Ellerman 	.segment_sizes_prop_len = 0,
5595477af3SMichael Ellerman 	.slb_size = 0,
5695477af3SMichael Ellerman 	.tb_freq = 33333333,
5795477af3SMichael Ellerman 	.d_bsize = 128,
5895477af3SMichael Ellerman 	.i_bsize = 128,
5995477af3SMichael Ellerman 	.flags = CPUINFO_FLAG_VMX,
60d391177aSMatt Evans };
61d391177aSMatt Evans 
62d391177aSMatt Evans /* This is a default catchall for 'no match' on PVR: */
6395477af3SMichael Ellerman static struct cpu_info cpu_dummy_info = { .name = "unknown" };
64d391177aSMatt Evans 
65d391177aSMatt Evans static struct pvr_info host_pvr_info[] = {
66d391177aSMatt Evans 	{ 0xffffffff, 0x0f000003, &cpu_power7_info },
67d391177aSMatt Evans 	{ 0xffff0000, 0x003f0000, &cpu_power7_info },
68d391177aSMatt Evans 	{ 0xffff0000, 0x004a0000, &cpu_power7_info },
69d391177aSMatt Evans 	{ 0xffff0000, 0x00390000, &cpu_970_info },
70d391177aSMatt Evans 	{ 0xffff0000, 0x003c0000, &cpu_970_info },
71d391177aSMatt Evans         { 0xffff0000, 0x00440000, &cpu_970_info },
72d391177aSMatt Evans         { 0xffff0000, 0x00450000, &cpu_970_info },
73d391177aSMatt Evans };
74d391177aSMatt Evans 
75d391177aSMatt Evans struct cpu_info *find_cpu_info(u32 pvr)
76d391177aSMatt Evans {
77d391177aSMatt Evans 	unsigned int i;
78*ac92dd43SMichael Ellerman 
792b5ca5cdSMichael Ellerman 	for (i = 0; i < ARRAY_SIZE(host_pvr_info); i++) {
80*ac92dd43SMichael Ellerman 		if ((pvr & host_pvr_info[i].pvr_mask) == host_pvr_info[i].pvr) {
81d391177aSMatt Evans 			return host_pvr_info[i].cpu_info;
82d391177aSMatt Evans 		}
83d391177aSMatt Evans 	}
84*ac92dd43SMichael Ellerman 
85d391177aSMatt Evans 	/* Didn't find anything? Rut-ro. */
86d391177aSMatt Evans 	pr_warning("Host CPU unsupported by kvmtool\n");
87*ac92dd43SMichael Ellerman 
88d391177aSMatt Evans 	return &cpu_dummy_info;
89d391177aSMatt Evans }
90