xref: /kvmtool/powerpc/cpu_info.c (revision 4a75c6033b84362ee65b12f2479f70834eb906d8)
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 
75*4a75c603SMichael Ellerman struct cpu_info *find_cpu_info(struct kvm *kvm)
76d391177aSMatt Evans {
77*4a75c603SMichael Ellerman 	struct cpu_info *info;
78d391177aSMatt Evans 	unsigned int i;
79*4a75c603SMichael Ellerman 	u32 pvr = kvm->pvr;
80ac92dd43SMichael Ellerman 
81*4a75c603SMichael Ellerman 	for (info = NULL, i = 0; i < ARRAY_SIZE(host_pvr_info); i++) {
82ac92dd43SMichael Ellerman 		if ((pvr & host_pvr_info[i].pvr_mask) == host_pvr_info[i].pvr) {
83*4a75c603SMichael Ellerman 			info = host_pvr_info[i].cpu_info;
84*4a75c603SMichael Ellerman 			break;
85d391177aSMatt Evans 		}
86d391177aSMatt Evans 	}
87ac92dd43SMichael Ellerman 
88d391177aSMatt Evans 	/* Didn't find anything? Rut-ro. */
89*4a75c603SMichael Ellerman 	if (!info) {
90d391177aSMatt Evans 		pr_warning("Host CPU unsupported by kvmtool\n");
91*4a75c603SMichael Ellerman 		info = &cpu_dummy_info;
92*4a75c603SMichael Ellerman 	}
93ac92dd43SMichael Ellerman 
94*4a75c603SMichael Ellerman 	return info;
95d391177aSMatt Evans }
96