Commit cad32d9d authored by Alexey Kardashevskiy's avatar Alexey Kardashevskiy Committed by Michael Ellerman
Browse files

KVM: PPC: Book3s: Retire H_PUT_TCE/etc real mode handlers



LoPAPR defines guest visible IOMMU with hypercalls to use it -
H_PUT_TCE/etc. Implemented first on POWER7 where hypercalls would trap
in the KVM in the real mode (with MMU off). The problem with the real mode
is some memory is not available and some API usage crashed the host but
enabling MMU was an expensive operation.

The problems with the real mode handlers are:
1. Occasionally these cannot complete the request so the code is
copied+modified to work in the virtual mode, very little is shared;
2. The real mode handlers have to be linked into vmlinux to work;
3. An exception in real mode immediately reboots the machine.

If the small DMA window is used, the real mode handlers bring better
performance. However since POWER8, there has always been a bigger DMA
window which VMs use to map the entire VM memory to avoid calling
H_PUT_TCE. Such 1:1 mapping happens once and uses H_PUT_TCE_INDIRECT
(a bulk version of H_PUT_TCE) which virtual mode handler is even closer
to its real mode version.

On POWER9 hypercalls trap straight to the virtual mode so the real mode
handlers never execute on POWER9 and later CPUs.

So with the current use of the DMA windows and MMU improvements in
POWER9 and later, there is no point in duplicating the code.
The 32bit passed through devices may slow down but we do not have many
of these in practice. For example, with this applied, a 1Gbit ethernet
adapter still demostrates above 800Mbit/s of actual throughput.

This removes the real mode handlers from KVM and related code from
the powernv platform.

This updates the list of implemented hcalls in KVM-HV as the realmode
handlers are removed.

This changes ABI - kvmppc_h_get_tce() moves to the KVM module and
kvmppc_find_table() is static now.

Signed-off-by: default avatarAlexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220506053755.3820702-1-aik@ozlabs.ru
parent 750137ec
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -51,13 +51,11 @@ struct iommu_table_ops {
	int (*xchg_no_kill)(struct iommu_table *tbl,
			long index,
			unsigned long *hpa,
			enum dma_data_direction *direction,
			bool realmode);
			enum dma_data_direction *direction);

	void (*tce_kill)(struct iommu_table *tbl,
			unsigned long index,
			unsigned long pages,
			bool realmode);
			unsigned long pages);

	__be64 *(*useraddrptr)(struct iommu_table *tbl, long index, bool alloc);
#endif
+0 −2
Original line number Diff line number Diff line
@@ -177,8 +177,6 @@ extern void kvmppc_setup_partition_table(struct kvm *kvm);

extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
				struct kvm_create_spapr_tce_64 *args);
extern struct kvmppc_spapr_tce_table *kvmppc_find_table(
		struct kvm *kvm, unsigned long liobn);
#define kvmppc_ioba_validate(stt, ioba, npages)                         \
		(iommu_tce_check_ioba((stt)->page_shift, (stt)->offset, \
				(stt)->size, (ioba), (npages)) ?        \
+0 −5
Original line number Diff line number Diff line
@@ -34,15 +34,10 @@ extern void mm_iommu_init(struct mm_struct *mm);
extern void mm_iommu_cleanup(struct mm_struct *mm);
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
		unsigned long ua, unsigned long size);
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(
		struct mm_struct *mm, unsigned long ua, unsigned long size);
extern struct mm_iommu_table_group_mem_t *mm_iommu_get(struct mm_struct *mm,
		unsigned long ua, unsigned long entries);
extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
		unsigned long ua, unsigned int pageshift, unsigned long *hpa);
extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
		unsigned long ua, unsigned int pageshift, unsigned long *hpa);
extern void mm_iommu_ua_mark_dirty_rm(struct mm_struct *mm, unsigned long ua);
extern bool mm_iommu_is_devmem(struct mm_struct *mm, unsigned long hpa,
		unsigned int pageshift, unsigned long *size);
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
+2 −2
Original line number Diff line number Diff line
@@ -1065,7 +1065,7 @@ extern long iommu_tce_xchg_no_kill(struct mm_struct *mm,
	long ret;
	unsigned long size = 0;

	ret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction, false);
	ret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction);
	if (!ret && ((*direction == DMA_FROM_DEVICE) ||
			(*direction == DMA_BIDIRECTIONAL)) &&
			!mm_iommu_is_devmem(mm, *hpa, tbl->it_page_shift,
@@ -1080,7 +1080,7 @@ void iommu_tce_kill(struct iommu_table *tbl,
		unsigned long entry, unsigned long pages)
{
	if (tbl->it_ops->tce_kill)
		tbl->it_ops->tce_kill(tbl, entry, pages, false);
		tbl->it_ops->tce_kill(tbl, entry, pages);
}
EXPORT_SYMBOL_GPL(iommu_tce_kill);

+0 −3
Original line number Diff line number Diff line
@@ -37,9 +37,6 @@ kvm-e500mc-objs := \
	e500_emulate.o
kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)

kvm-book3s_64-builtin-objs-$(CONFIG_SPAPR_TCE_IOMMU) := \
	book3s_64_vio_hv.o

kvm-pr-y := \
	fpu.o \
	emulate.o \
Loading