2 * PPC CPU identification
4 * This is a very simple "host CPU info" struct to get us going.
5 * For the little host information we need, I don't want to grub about
6 * parsing stuff in /proc/device-tree so just match host PVR to differentiate
7 * PPC970 and POWER7 (which is all that's currently supported).
9 * Qemu does something similar but this is MUCH simpler!
11 * Copyright 2012 Matt Evans <matt@ozlabs.org>, IBM Corporation.
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License version 2 as published
15 * by the Free Software Foundation.
19 #include <sys/ioctl.h>
26 static struct cpu_info cpu_power7_info = {
31 .flags = CPUINFO_FLAG_DFP | CPUINFO_FLAG_VSX | CPUINFO_FLAG_VMX,
33 .flags = KVM_PPC_PAGE_SIZES_REAL | KVM_PPC_1T_SEGMENTS,
40 static struct cpu_info cpu_970_info = {
45 .flags = CPUINFO_FLAG_VMX,
48 /* This is a default catchall for 'no match' on PVR: */
49 static struct cpu_info cpu_dummy_info = { .name = "unknown" };
51 static struct pvr_info host_pvr_info[] = {
52 { 0xffffffff, 0x0f000003, &cpu_power7_info },
53 { 0xffff0000, 0x003f0000, &cpu_power7_info },
54 { 0xffff0000, 0x004a0000, &cpu_power7_info },
55 { 0xffff0000, 0x00390000, &cpu_970_info },
56 { 0xffff0000, 0x003c0000, &cpu_970_info },
57 { 0xffff0000, 0x00440000, &cpu_970_info },
58 { 0xffff0000, 0x00450000, &cpu_970_info },
61 /* If we can't query the kernel for supported page sizes assume 4K and 16M */
62 static struct kvm_ppc_one_seg_page_size fallback_sps[] = {
86 static void setup_mmu_info(struct kvm *kvm, struct cpu_info *cpu_info)
88 static struct kvm_ppc_smmu_info *mmu_info;
89 struct kvm_ppc_one_seg_page_size *sps;
92 if (!kvm__supports_extension(kvm, KVM_CAP_PPC_GET_SMMU_INFO)) {
93 memcpy(&cpu_info->mmu_info.sps, fallback_sps, sizeof(fallback_sps));
94 } else if (ioctl(kvm->vm_fd, KVM_PPC_GET_SMMU_INFO, &cpu_info->mmu_info) < 0) {
95 die_perror("KVM_PPC_GET_SMMU_INFO failed");
98 mmu_info = &cpu_info->mmu_info;
100 if (!(mmu_info->flags & KVM_PPC_PAGE_SIZES_REAL))
101 /* Guest pages are not restricted by the backing page size */
104 /* Filter based on backing page size */
106 for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
107 sps = &mmu_info->sps[i];
109 if (!sps->page_shift)
112 if (kvm->ram_pagesize < (1ul << sps->page_shift)) {
113 /* Mark the whole segment size invalid */
118 /* Check each page size for the segment */
119 for (j = 0, valid = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
120 if (!sps->enc[j].page_shift)
123 if (kvm->ram_pagesize < (1ul << sps->enc[j].page_shift))
124 sps->enc[j].page_shift = 0;
130 /* Mark the whole segment size invalid */
135 /* Mark any trailing entries invalid if we broke out early */
136 for (k = j; k < KVM_PPC_PAGE_SIZES_MAX_SZ; k++)
137 sps->enc[k].page_shift = 0;
140 for (j = 0; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
141 if (sps->enc[j].page_shift)
144 for (k = j + 1; k < KVM_PPC_PAGE_SIZES_MAX_SZ; k++) {
145 if (sps->enc[k].page_shift) {
146 sps->enc[j] = sps->enc[k];
147 sps->enc[k].page_shift = 0;
154 /* Mark any trailing entries invalid if we broke out early */
155 for (j = i; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++)
156 mmu_info->sps[j].page_shift = 0;
159 for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
160 if (mmu_info->sps[i].page_shift)
163 for (j = i + 1; j < KVM_PPC_PAGE_SIZES_MAX_SZ; j++) {
164 if (mmu_info->sps[j].page_shift) {
165 mmu_info->sps[i] = mmu_info->sps[j];
166 mmu_info->sps[j].page_shift = 0;
173 struct cpu_info *find_cpu_info(struct kvm *kvm)
175 struct cpu_info *info;
177 u32 pvr = kvm->arch.pvr;
179 for (info = NULL, i = 0; i < ARRAY_SIZE(host_pvr_info); i++) {
180 if ((pvr & host_pvr_info[i].pvr_mask) == host_pvr_info[i].pvr) {
181 info = host_pvr_info[i].cpu_info;
186 /* Didn't find anything? Rut-ro. */
188 pr_warning("Host CPU unsupported by kvmtool\n");
189 info = &cpu_dummy_info;
192 setup_mmu_info(kvm, info);