kvm/powerpc: Add new ioctl to retreive server MMU infos
This is necessary for qemu to be able to pass the right information to the guest, such as the supported page sizes and corresponding encodings in the SLB and hash table, which can vary depending on the processor type, the type of KVM used (PR vs HV) and the version of KVM Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [agraf: fix compilation on hv, adjust for newer ioctl numbers] Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Родитель
f31e65e117
Коммит
5b74716eba
|
@ -1860,6 +1860,76 @@ See KVM_GET_PIT2 for details on struct kvm_pit_state2.
|
|||
This IOCTL replaces the obsolete KVM_SET_PIT.
|
||||
|
||||
|
||||
4.74 KVM_PPC_GET_SMMU_INFO
|
||||
|
||||
Capability: KVM_CAP_PPC_GET_SMMU_INFO
|
||||
Architectures: powerpc
|
||||
Type: vm ioctl
|
||||
Parameters: None
|
||||
Returns: 0 on success, -1 on error
|
||||
|
||||
This populates and returns a structure describing the features of
|
||||
the "Server" class MMU emulation supported by KVM.
|
||||
This can in turn be used by userspace to generate the appropariate
|
||||
device-tree properties for the guest operating system.
|
||||
|
||||
The structure contains some global informations, followed by an
|
||||
array of supported segment page sizes:
|
||||
|
||||
struct kvm_ppc_smmu_info {
|
||||
__u64 flags;
|
||||
__u32 slb_size;
|
||||
__u32 pad;
|
||||
struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
|
||||
};
|
||||
|
||||
The supported flags are:
|
||||
|
||||
- KVM_PPC_PAGE_SIZES_REAL:
|
||||
When that flag is set, guest page sizes must "fit" the backing
|
||||
store page sizes. When not set, any page size in the list can
|
||||
be used regardless of how they are backed by userspace.
|
||||
|
||||
- KVM_PPC_1T_SEGMENTS
|
||||
The emulated MMU supports 1T segments in addition to the
|
||||
standard 256M ones.
|
||||
|
||||
The "slb_size" field indicates how many SLB entries are supported
|
||||
|
||||
The "sps" array contains 8 entries indicating the supported base
|
||||
page sizes for a segment in increasing order. Each entry is defined
|
||||
as follow:
|
||||
|
||||
struct kvm_ppc_one_seg_page_size {
|
||||
__u32 page_shift; /* Base page shift of segment (or 0) */
|
||||
__u32 slb_enc; /* SLB encoding for BookS */
|
||||
struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
|
||||
};
|
||||
|
||||
An entry with a "page_shift" of 0 is unused. Because the array is
|
||||
organized in increasing order, a lookup can stop when encoutering
|
||||
such an entry.
|
||||
|
||||
The "slb_enc" field provides the encoding to use in the SLB for the
|
||||
page size. The bits are in positions such as the value can directly
|
||||
be OR'ed into the "vsid" argument of the slbmte instruction.
|
||||
|
||||
The "enc" array is a list which for each of those segment base page
|
||||
size provides the list of supported actual page sizes (which can be
|
||||
only larger or equal to the base page size), along with the
|
||||
corresponding encoding in the hash PTE. Similarily, the array is
|
||||
8 entries sorted by increasing sizes and an entry with a "0" shift
|
||||
is an empty entry and a terminator:
|
||||
|
||||
struct kvm_ppc_one_page_size {
|
||||
__u32 page_shift; /* Page shift (or 0) */
|
||||
__u32 pte_enc; /* Encoding in the HPTE (>>12) */
|
||||
};
|
||||
|
||||
The "pte_enc" field provides a value that can OR'ed into the hash
|
||||
PTE's RPN field (ie, it needs to be shifted left by 12 to OR it
|
||||
into the hash PTE second double word).
|
||||
|
||||
5. The kvm_run structure
|
||||
------------------------
|
||||
|
||||
|
|
|
@ -140,6 +140,8 @@ extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
|
|||
struct kvm_userspace_memory_region *mem);
|
||||
extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
|
||||
struct kvm_userspace_memory_region *mem);
|
||||
extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
|
||||
struct kvm_ppc_smmu_info *info);
|
||||
|
||||
extern int kvmppc_bookehv_init(void);
|
||||
extern void kvmppc_bookehv_exit(void);
|
||||
|
|
|
@ -190,3 +190,7 @@ EXPORT_SYMBOL(__arch_hweight16);
|
|||
EXPORT_SYMBOL(__arch_hweight32);
|
||||
EXPORT_SYMBOL(__arch_hweight64);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
EXPORT_SYMBOL_GPL(mmu_psize_defs);
|
||||
#endif
|
||||
|
|
|
@ -1175,6 +1175,38 @@ long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret)
|
|||
return fd;
|
||||
}
|
||||
|
||||
static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps,
|
||||
int linux_psize)
|
||||
{
|
||||
struct mmu_psize_def *def = &mmu_psize_defs[linux_psize];
|
||||
|
||||
if (!def->shift)
|
||||
return;
|
||||
(*sps)->page_shift = def->shift;
|
||||
(*sps)->slb_enc = def->sllp;
|
||||
(*sps)->enc[0].page_shift = def->shift;
|
||||
(*sps)->enc[0].pte_enc = def->penc;
|
||||
(*sps)++;
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info)
|
||||
{
|
||||
struct kvm_ppc_one_seg_page_size *sps;
|
||||
|
||||
info->flags = KVM_PPC_PAGE_SIZES_REAL;
|
||||
if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
|
||||
info->flags |= KVM_PPC_1T_SEGMENTS;
|
||||
info->slb_size = mmu_slb_size;
|
||||
|
||||
/* We only support these sizes for now, and no muti-size segments */
|
||||
sps = &info->sps[0];
|
||||
kvmppc_add_seg_page_size(&sps, MMU_PAGE_4K);
|
||||
kvmppc_add_seg_page_size(&sps, MMU_PAGE_64K);
|
||||
kvmppc_add_seg_page_size(&sps, MMU_PAGE_16M);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get (and clear) the dirty memory log for a memory slot.
|
||||
*/
|
||||
|
|
|
@ -1158,6 +1158,31 @@ out:
|
|||
return r;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info)
|
||||
{
|
||||
/* No flags */
|
||||
info->flags = 0;
|
||||
|
||||
/* SLB is always 64 entries */
|
||||
info->slb_size = 64;
|
||||
|
||||
/* Standard 4k base page size segment */
|
||||
info->sps[0].page_shift = 12;
|
||||
info->sps[0].slb_enc = 0;
|
||||
info->sps[0].enc[0].page_shift = 12;
|
||||
info->sps[0].enc[0].pte_enc = 0;
|
||||
|
||||
/* Standard 16M large page size segment */
|
||||
info->sps[1].page_shift = 24;
|
||||
info->sps[1].slb_enc = SLB_VSID_L;
|
||||
info->sps[1].enc[0].page_shift = 24;
|
||||
info->sps[1].enc[0].pte_enc = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
int kvmppc_core_prepare_memory_region(struct kvm *kvm,
|
||||
struct kvm_userspace_memory_region *mem)
|
||||
{
|
||||
|
|
|
@ -279,6 +279,11 @@ int kvm_dev_ioctl_check_extension(long ext)
|
|||
case KVM_CAP_MAX_VCPUS:
|
||||
r = KVM_MAX_VCPUS;
|
||||
break;
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
case KVM_CAP_PPC_GET_SMMU_INFO:
|
||||
r = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
|
@ -718,7 +723,6 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
r = -EINVAL;
|
||||
}
|
||||
|
@ -800,6 +804,18 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
|||
}
|
||||
#endif /* CONFIG_KVM_BOOK3S_64_HV */
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
case KVM_PPC_GET_SMMU_INFO: {
|
||||
struct kvm *kvm = filp->private_data;
|
||||
struct kvm_ppc_smmu_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
r = kvm_vm_ioctl_get_smmu_info(kvm, &info);
|
||||
if (r >= 0 && copy_to_user(argp, &info, sizeof(info)))
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S_64 */
|
||||
default:
|
||||
r = -ENOTTY;
|
||||
}
|
||||
|
|
|
@ -449,6 +449,30 @@ struct kvm_ppc_pvinfo {
|
|||
__u8 pad[108];
|
||||
};
|
||||
|
||||
/* for KVM_PPC_GET_SMMU_INFO */
|
||||
#define KVM_PPC_PAGE_SIZES_MAX_SZ 8
|
||||
|
||||
struct kvm_ppc_one_page_size {
|
||||
__u32 page_shift; /* Page shift (or 0) */
|
||||
__u32 pte_enc; /* Encoding in the HPTE (>>12) */
|
||||
};
|
||||
|
||||
struct kvm_ppc_one_seg_page_size {
|
||||
__u32 page_shift; /* Base page shift of segment (or 0) */
|
||||
__u32 slb_enc; /* SLB encoding for BookS */
|
||||
struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
|
||||
};
|
||||
|
||||
#define KVM_PPC_PAGE_SIZES_REAL 0x00000001
|
||||
#define KVM_PPC_1T_SEGMENTS 0x00000002
|
||||
|
||||
struct kvm_ppc_smmu_info {
|
||||
__u64 flags;
|
||||
__u32 slb_size;
|
||||
__u32 pad;
|
||||
struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
|
||||
};
|
||||
|
||||
#define KVMIO 0xAE
|
||||
|
||||
/* machine type bits, to be used as argument to KVM_CREATE_VM */
|
||||
|
@ -591,6 +615,7 @@ struct kvm_ppc_pvinfo {
|
|||
#define KVM_CAP_PCI_2_3 75
|
||||
#define KVM_CAP_KVMCLOCK_CTRL 76
|
||||
#define KVM_CAP_SIGNAL_MSI 77
|
||||
#define KVM_CAP_PPC_GET_SMMU_INFO 78
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
|
@ -800,6 +825,8 @@ struct kvm_s390_ucas_mapping {
|
|||
struct kvm_assigned_pci_dev)
|
||||
/* Available with KVM_CAP_SIGNAL_MSI */
|
||||
#define KVM_SIGNAL_MSI _IOW(KVMIO, 0xa5, struct kvm_msi)
|
||||
/* Available with KVM_CAP_PPC_GET_SMMU_INFO */
|
||||
#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
|
||||
|
||||
/*
|
||||
* ioctls for vcpu fds
|
||||
|
|
Загрузка…
Ссылка в новой задаче