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