* Re: [PATCH v3 1/3] PCI: Introduce pcibios_ignore_alignment_request
From: Alexey Kardashevskiy @ 2019-05-28 6:27 UTC (permalink / raw)
To: Oliver, Shawn Anastasio
Cc: Sam Bobroff, linux-pci, Linux Kernel Mailing List, rppt,
Paul Mackerras, Bjorn Helgaas, xyjxie, linuxppc-dev
In-Reply-To: <CAOSf1CEFfbmwfvmdqT1xdt8SFb=tYdYXLfXeyZ8=iRnhg4a3Pg@mail.gmail.com>
On 28/05/2019 15:36, Oliver wrote:
> On Tue, May 28, 2019 at 2:03 PM Shawn Anastasio <shawn@anastas.io> wrote:
>>
>> Introduce a new pcibios function pcibios_ignore_alignment_request
>> which allows the PCI core to defer to platform-specific code to
>> determine whether or not to ignore alignment requests for PCI resources.
>>
>> The existing behavior is to simply ignore alignment requests when
>> PCI_PROBE_ONLY is set. This is behavior is maintained by the
>> default implementation of pcibios_ignore_alignment_request.
>>
>> Signed-off-by: Shawn Anastasio <shawn@anastas.io>
>> ---
>> drivers/pci/pci.c | 9 +++++++--
>> include/linux/pci.h | 1 +
>> 2 files changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>> index 8abc843b1615..8207a09085d1 100644
>> --- a/drivers/pci/pci.c
>> +++ b/drivers/pci/pci.c
>> @@ -5882,6 +5882,11 @@ resource_size_t __weak pcibios_default_alignment(void)
>> return 0;
>> }
>>
>> +int __weak pcibios_ignore_alignment_request(void)
>> +{
>> + return pci_has_flag(PCI_PROBE_ONLY);
>> +}
>> +
>> #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
>> static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
>> static DEFINE_SPINLOCK(resource_alignment_lock);
>> @@ -5906,9 +5911,9 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
>> p = resource_alignment_param;
>> if (!*p && !align)
>> goto out;
>> - if (pci_has_flag(PCI_PROBE_ONLY)) {
>> + if (pcibios_ignore_alignment_request()) {
>> align = 0;
>> - pr_info_once("PCI: Ignoring requested alignments (PCI_PROBE_ONLY)\n");
>> + pr_info_once("PCI: Ignoring requested alignments\n");
>> goto out;
>> }
>
> I think the logic here is questionable to begin with. If the user has
> explicitly requested re-aligning a resource via the command line then
> we should probably do it even if PCI_PROBE_ONLY is set. When it breaks
> they get to keep the pieces.
>
> That said, the real issue here is that PCI_PROBE_ONLY probably
> shouldn't be set under qemu/kvm. Under the other hypervisor (PowerVM)
> hotplugged devices are configured by firmware before it's passed to
> the guest and we need to keep the FW assignments otherwise things
> break. QEMU however doesn't do any BAR assignments and relies on that
> being handled by the guest. At boot time this is done by SLOF, but
> Linux only keeps SLOF around until it's extracted the device-tree.
> Once that's done SLOF gets blown away and the kernel needs to do it's
> own BAR assignments. I'm guessing there's a hack in there to make it
> work today, but it's a little surprising that it works at all...
The hack is to run a modified qemu-aware "/usr/sbin/rtas_errd" in the
guest which receives an event from qemu (RAS_EPOW from
/proc/interrupts), fetches device tree chunks (and as I understand it -
they come with BARs from phyp but without from qemu) and writes "1" to
"/sys/bus/pci/rescan" which calls pci_assign_resource() eventually:
[c000000006e6f960] [c0000000005f62d4] pci_assign_resource+0x44/0x360
[c000000006e6fa10] [c0000000005f8b54]
assign_requested_resources_sorted+0x84/0x110
[c000000006e6fa60] [c0000000005f9540] __assign_resources_sorted+0xd0/0x750
[c000000006e6fb40] [c0000000005fb2e0]
__pci_bus_assign_resources+0x80/0x280
[c000000006e6fc00] [c0000000005fb95c]
pci_assign_unassigned_bus_resources+0xbc/0x100
[c000000006e6fc60] [c0000000005e3d74] pci_rescan_bus+0x34/0x60
[c000000006e6fc90] [c0000000005f1ef4] rescan_store+0x84/0xc0
[c000000006e6fcd0] [c00000000068060c] bus_attr_store+0x3c/0x60
[c000000006e6fcf0] [c00000000037853c] sysfs_kf_write+0x5c/0x80
>
> IIRC Sam Bobroff was looking at hotplug under pseries recently so he
> might have something to add. He's sick at the moment, but I'll ask him
> to take a look at this once he's back among the living
>
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 4a5a84d7bdd4..47471dcdbaf9 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -1990,6 +1990,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) {}
>> int pcibios_alloc_irq(struct pci_dev *dev);
>> void pcibios_free_irq(struct pci_dev *dev);
>> resource_size_t pcibios_default_alignment(void);
>> +int pcibios_ignore_alignment_request(void);
>>
>> #ifdef CONFIG_HIBERNATE_CALLBACKS
>> extern struct dev_pm_ops pcibios_pm_ops;
>> --
>> 2.20.1
>>
--
Alexey
^ permalink raw reply
* [PATCH v4 0/6] kvmppc: HMM driver to manage pages of secure guest
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
Hi,
A pseries guest can be run as a secure guest on Ultravisor-enabled
POWER platforms. On such platforms, this driver will be used to manage
the movement of guest pages between the normal memory managed by
hypervisor (HV) and secure memory managed by Ultravisor (UV).
Private ZONE_DEVICE memory equal to the amount of secure memory
available in the platform for running secure guests is created
via a HMM device. The movement of pages between normal and secure
memory is done by ->alloc_and_copy() callback routine of migrate_vma().
The page-in or page-out requests from UV will come to HV as hcalls and
HV will call back into UV via uvcalls to satisfy these page requests.
These patches apply and work on top of the base Ultravisor patches
posted by Claudio Carvalho at:
https://lists.ozlabs.org/pipermail/linuxppc-dev/2019-May/190694.html
In this version, the last two patches are the new additions.
Changes in v4
=============
- Handling HV side page invalidations by issuing UV_PAGE_INVAL ucall
- Handling HV side radix page faults by sending the page to UV
- Support for rebooting a secure guest
- Some cleanups and code reorgs
v3: https://lists.ozlabs.org/pipermail/linuxppc-dev/2019-January/184731.html
Bharata B Rao (6):
kvmppc: HMM backend driver to manage pages of secure guest
kvmppc: Shared pages support for secure guests
kvmppc: H_SVM_INIT_START and H_SVM_INIT_DONE hcalls
kvmppc: Handle memory plug/unplug to secure VM
kvmppc: Radix changes for secure guest
kvmppc: Support reset of secure guest
arch/powerpc/include/asm/hvcall.h | 9 +
arch/powerpc/include/asm/kvm_book3s_hmm.h | 41 ++
arch/powerpc/include/asm/kvm_host.h | 37 ++
arch/powerpc/include/asm/kvm_ppc.h | 4 +
arch/powerpc/include/asm/ultravisor-api.h | 6 +
arch/powerpc/include/asm/ultravisor.h | 47 ++
arch/powerpc/kvm/Makefile | 3 +
arch/powerpc/kvm/book3s_64_mmu_radix.c | 19 +
arch/powerpc/kvm/book3s_hv.c | 69 +++
arch/powerpc/kvm/book3s_hv_hmm.c | 666 ++++++++++++++++++++++
arch/powerpc/kvm/powerpc.c | 12 +
include/uapi/linux/kvm.h | 1 +
tools/include/uapi/linux/kvm.h | 1 +
13 files changed, 915 insertions(+)
create mode 100644 arch/powerpc/include/asm/kvm_book3s_hmm.h
create mode 100644 arch/powerpc/kvm/book3s_hv_hmm.c
--
2.17.1
^ permalink raw reply
* [PATCH v4 1/6] kvmppc: HMM backend driver to manage pages of secure guest
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
In-Reply-To: <20190528064933.23119-1-bharata@linux.ibm.com>
HMM driver for KVM PPC to manage page transitions of
secure guest via H_SVM_PAGE_IN and H_SVM_PAGE_OUT hcalls.
H_SVM_PAGE_IN: Move the content of a normal page to secure page
H_SVM_PAGE_OUT: Move the content of a secure page to normal page
Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 4 +
arch/powerpc/include/asm/kvm_book3s_hmm.h | 29 ++
arch/powerpc/include/asm/kvm_host.h | 14 +
arch/powerpc/include/asm/ultravisor-api.h | 2 +
arch/powerpc/include/asm/ultravisor.h | 17 +
arch/powerpc/kvm/Makefile | 3 +
arch/powerpc/kvm/book3s_hv.c | 20 +
arch/powerpc/kvm/book3s_hv_hmm.c | 474 ++++++++++++++++++++++
8 files changed, 563 insertions(+)
create mode 100644 arch/powerpc/include/asm/kvm_book3s_hmm.h
create mode 100644 arch/powerpc/kvm/book3s_hv_hmm.c
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 463c63a9fcf1..2f6b952deb0f 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -337,6 +337,10 @@
#define H_TLB_INVALIDATE 0xF808
#define H_COPY_TOFROM_GUEST 0xF80C
+/* Platform-specific hcalls used by the Ultravisor */
+#define H_SVM_PAGE_IN 0xEF00
+#define H_SVM_PAGE_OUT 0xEF04
+
/* Values for 2nd argument to H_SET_MODE */
#define H_SET_MODE_RESOURCE_SET_CIABR 1
#define H_SET_MODE_RESOURCE_SET_DAWR 2
diff --git a/arch/powerpc/include/asm/kvm_book3s_hmm.h b/arch/powerpc/include/asm/kvm_book3s_hmm.h
new file mode 100644
index 000000000000..21f3de5f2acb
--- /dev/null
+++ b/arch/powerpc/include/asm/kvm_book3s_hmm.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __POWERPC_KVM_PPC_HMM_H__
+#define __POWERPC_KVM_PPC_HMM_H__
+
+#ifdef CONFIG_PPC_UV
+extern unsigned long kvmppc_h_svm_page_in(struct kvm *kvm,
+ unsigned long gra,
+ unsigned long flags,
+ unsigned long page_shift);
+extern unsigned long kvmppc_h_svm_page_out(struct kvm *kvm,
+ unsigned long gra,
+ unsigned long flags,
+ unsigned long page_shift);
+#else
+static inline unsigned long
+kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gra,
+ unsigned long flags, unsigned long page_shift)
+{
+ return H_UNSUPPORTED;
+}
+
+static inline unsigned long
+kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gra,
+ unsigned long flags, unsigned long page_shift)
+{
+ return H_UNSUPPORTED;
+}
+#endif /* CONFIG_PPC_UV */
+#endif /* __POWERPC_KVM_PPC_HMM_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 184becb62ea4..c0c9c3455ac4 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -858,4 +858,18 @@ static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
+#ifdef CONFIG_PPC_UV
+extern int kvmppc_hmm_init(void);
+extern void kvmppc_hmm_free(void);
+extern void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free);
+#else
+static inline int kvmppc_hmm_init(void)
+{
+ return 0;
+}
+
+static inline void kvmppc_hmm_free(void) {}
+static inline void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free) {}
+#endif /* CONFIG_PPC_UV */
+
#endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
index 15e6ce77a131..51c4e0b5d197 100644
--- a/arch/powerpc/include/asm/ultravisor-api.h
+++ b/arch/powerpc/include/asm/ultravisor-api.h
@@ -20,5 +20,7 @@
/* opcodes */
#define UV_WRITE_PATE 0xF104
#define UV_RETURN 0xF11C
+#define UV_PAGE_IN 0xF128
+#define UV_PAGE_OUT 0xF12C
#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
index 4ffec7a36acd..1e4c51799b43 100644
--- a/arch/powerpc/include/asm/ultravisor.h
+++ b/arch/powerpc/include/asm/ultravisor.h
@@ -44,6 +44,23 @@ static inline int uv_register_pate(u64 lpid, u64 dw0, u64 dw1)
return ucall(UV_WRITE_PATE, retbuf, lpid, dw0, dw1);
}
+static inline int uv_page_in(u64 lpid, u64 src_ra, u64 dst_gpa, u64 flags,
+ u64 page_shift)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_PAGE_IN, retbuf, lpid, src_ra, dst_gpa, flags,
+ page_shift);
+}
+
+static inline int uv_page_out(u64 lpid, u64 dst_ra, u64 src_gpa, u64 flags,
+ u64 page_shift)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_PAGE_OUT, retbuf, lpid, dst_ra, src_gpa, flags,
+ page_shift);
+}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 4c67cc79de7c..d1a79fb5f806 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -71,6 +71,9 @@ kvm-hv-y += \
book3s_64_mmu_radix.o \
book3s_hv_nested.o
+kvm-hv-$(CONFIG_PPC_UV) += \
+ book3s_hv_hmm.o
+
kvm-hv-$(CONFIG_PPC_TRANSACTIONAL_MEM) += \
book3s_hv_tm.o
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 57ce45a997c7..2918616198de 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -76,6 +76,8 @@
#include <asm/xive.h>
#include <asm/hw_breakpoint.h>
#include <asm/firmware.h>
+#include <asm/kvm_host.h>
+#include <asm/kvm_book3s_hmm.h>
#include "book3s.h"
@@ -1084,6 +1086,18 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
kvmppc_get_gpr(vcpu, 5),
kvmppc_get_gpr(vcpu, 6));
break;
+ case H_SVM_PAGE_IN:
+ ret = kvmppc_h_svm_page_in(vcpu->kvm,
+ kvmppc_get_gpr(vcpu, 4),
+ kvmppc_get_gpr(vcpu, 5),
+ kvmppc_get_gpr(vcpu, 6));
+ break;
+ case H_SVM_PAGE_OUT:
+ ret = kvmppc_h_svm_page_out(vcpu->kvm,
+ kvmppc_get_gpr(vcpu, 4),
+ kvmppc_get_gpr(vcpu, 5),
+ kvmppc_get_gpr(vcpu, 6));
+ break;
default:
return RESUME_HOST;
}
@@ -4421,6 +4435,7 @@ static void kvmppc_core_free_memslot_hv(struct kvm_memory_slot *free,
struct kvm_memory_slot *dont)
{
if (!dont || free->arch.rmap != dont->arch.rmap) {
+ kvmppc_hmm_release_pfns(free);
vfree(free->arch.rmap);
free->arch.rmap = NULL;
}
@@ -5494,11 +5509,16 @@ static int kvmppc_book3s_init_hv(void)
no_mixing_hpt_and_radix = true;
}
+ r = kvmppc_hmm_init();
+ if (r < 0)
+ pr_err("KVM-HV: kvmppc_hmm_init failed %d\n", r);
+
return r;
}
static void kvmppc_book3s_exit_hv(void)
{
+ kvmppc_hmm_free();
kvmppc_free_host_rm_ops();
if (kvmppc_radix_possible())
kvmppc_radix_exit();
diff --git a/arch/powerpc/kvm/book3s_hv_hmm.c b/arch/powerpc/kvm/book3s_hv_hmm.c
new file mode 100644
index 000000000000..713806003da3
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_hv_hmm.c
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * HMM driver to manage page migration between normal and secure
+ * memory.
+ *
+ * Based on Jérôme Glisse's HMM dummy driver.
+ *
+ * Copyright 2018 Bharata B Rao, IBM Corp. <bharata@linux.ibm.com>
+ */
+
+/*
+ * A pseries guest can be run as a secure guest on Ultravisor-enabled
+ * POWER platforms. On such platforms, this driver will be used to manage
+ * the movement of guest pages between the normal memory managed by
+ * hypervisor (HV) and secure memory managed by Ultravisor (UV).
+ *
+ * Private ZONE_DEVICE memory equal to the amount of secure memory
+ * available in the platform for running secure guests is created
+ * via a HMM device. The movement of pages between normal and secure
+ * memory is done by ->alloc_and_copy() callback routine of migrate_vma().
+ *
+ * The page-in or page-out requests from UV will come to HV as hcalls and
+ * HV will call back into UV via uvcalls to satisfy these page requests.
+ *
+ * For each page that gets moved into secure memory, a HMM PFN is used
+ * on the HV side and HMM migration PTE corresponding to that PFN would be
+ * populated in the QEMU page tables.
+ */
+
+#include <linux/hmm.h>
+#include <linux/kvm_host.h>
+#include <linux/sched/mm.h>
+#include <asm/ultravisor.h>
+
+struct kvmppc_hmm_device {
+ struct hmm_device *device;
+ struct hmm_devmem *devmem;
+ unsigned long *pfn_bitmap;
+};
+
+static struct kvmppc_hmm_device kvmppc_hmm;
+spinlock_t kvmppc_hmm_lock;
+
+struct kvmppc_hmm_page_pvt {
+ unsigned long *rmap;
+ unsigned int lpid;
+ unsigned long gpa;
+};
+
+struct kvmppc_hmm_migrate_args {
+ unsigned long *rmap;
+ unsigned int lpid;
+ unsigned long gpa;
+ unsigned long page_shift;
+};
+
+#define KVMPPC_PFN_HMM (0x1ULL << 61)
+
+static inline bool kvmppc_is_hmm_pfn(unsigned long pfn)
+{
+ return !!(pfn & KVMPPC_PFN_HMM);
+}
+
+void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free)
+{
+ int i;
+
+ for (i = 0; i < free->npages; i++) {
+ unsigned long *rmap = &free->arch.rmap[i];
+
+ if (kvmppc_is_hmm_pfn(*rmap))
+ put_page(pfn_to_page(*rmap & ~KVMPPC_PFN_HMM));
+ }
+}
+
+/*
+ * Get a free HMM PFN from the pool
+ *
+ * Called when a normal page is moved to secure memory (UV_PAGE_IN). HMM
+ * PFN will be used to keep track of the secure page on HV side.
+ */
+/*
+ * TODO: In this and subsequent functions, we pass around and access
+ * individual elements of kvm_memory_slot->arch.rmap[] without any
+ * protection. Figure out the safe way to access this.
+ */
+static struct page *kvmppc_hmm_get_page(unsigned long *rmap,
+ unsigned long gpa, unsigned int lpid)
+{
+ struct page *dpage = NULL;
+ unsigned long bit, hmm_pfn;
+ unsigned long nr_pfns = kvmppc_hmm.devmem->pfn_last -
+ kvmppc_hmm.devmem->pfn_first;
+ unsigned long flags;
+ struct kvmppc_hmm_page_pvt *pvt;
+
+ if (kvmppc_is_hmm_pfn(*rmap))
+ return NULL;
+
+ spin_lock_irqsave(&kvmppc_hmm_lock, flags);
+ bit = find_first_zero_bit(kvmppc_hmm.pfn_bitmap, nr_pfns);
+ if (bit >= nr_pfns)
+ goto out;
+
+ bitmap_set(kvmppc_hmm.pfn_bitmap, bit, 1);
+ hmm_pfn = bit + kvmppc_hmm.devmem->pfn_first;
+ dpage = pfn_to_page(hmm_pfn);
+
+ if (!trylock_page(dpage))
+ goto out_clear;
+
+ *rmap = hmm_pfn | KVMPPC_PFN_HMM;
+ pvt = kzalloc(sizeof(*pvt), GFP_ATOMIC);
+ if (!pvt)
+ goto out_unlock;
+ pvt->rmap = rmap;
+ pvt->gpa = gpa;
+ pvt->lpid = lpid;
+ hmm_devmem_page_set_drvdata(dpage, (unsigned long)pvt);
+ spin_unlock_irqrestore(&kvmppc_hmm_lock, flags);
+
+ get_page(dpage);
+ return dpage;
+
+out_unlock:
+ unlock_page(dpage);
+out_clear:
+ bitmap_clear(kvmppc_hmm.pfn_bitmap,
+ hmm_pfn - kvmppc_hmm.devmem->pfn_first, 1);
+out:
+ spin_unlock_irqrestore(&kvmppc_hmm_lock, flags);
+ return NULL;
+}
+
+/*
+ * Release the HMM PFN back to the pool
+ *
+ * Called when secure page becomes a normal page during UV_PAGE_OUT.
+ */
+static void kvmppc_hmm_put_page(struct page *page)
+{
+ unsigned long pfn = page_to_pfn(page);
+ unsigned long flags;
+ struct kvmppc_hmm_page_pvt *pvt;
+
+ spin_lock_irqsave(&kvmppc_hmm_lock, flags);
+ pvt = (struct kvmppc_hmm_page_pvt *)hmm_devmem_page_get_drvdata(page);
+ hmm_devmem_page_set_drvdata(page, 0);
+
+ bitmap_clear(kvmppc_hmm.pfn_bitmap,
+ pfn - kvmppc_hmm.devmem->pfn_first, 1);
+ *(pvt->rmap) = 0;
+ spin_unlock_irqrestore(&kvmppc_hmm_lock, flags);
+ kfree(pvt);
+}
+
+/*
+ * migrate_vma() callback to move page from normal memory to secure memory.
+ *
+ * We don't capture the return value of uv_page_in() here because when
+ * UV asks for a page and then fails to copy it over, we don't care.
+ */
+static void
+kvmppc_hmm_migrate_alloc_and_copy(struct vm_area_struct *vma,
+ const unsigned long *src_pfn,
+ unsigned long *dst_pfn,
+ unsigned long start,
+ unsigned long end,
+ void *private)
+{
+ struct kvmppc_hmm_migrate_args *args = private;
+ struct page *spage = migrate_pfn_to_page(*src_pfn);
+ unsigned long pfn = *src_pfn >> MIGRATE_PFN_SHIFT;
+ struct page *dpage;
+
+ *dst_pfn = 0;
+ if (!(*src_pfn & MIGRATE_PFN_MIGRATE))
+ return;
+
+ dpage = kvmppc_hmm_get_page(args->rmap, args->gpa, args->lpid);
+ if (!dpage)
+ return;
+
+ if (spage)
+ uv_page_in(args->lpid, pfn << args->page_shift,
+ args->gpa, 0, args->page_shift);
+
+ *dst_pfn = migrate_pfn(page_to_pfn(dpage)) |
+ MIGRATE_PFN_DEVICE | MIGRATE_PFN_LOCKED;
+}
+
+/*
+ * This migrate_vma() callback is typically used to updated device
+ * page tables after successful migration. We have nothing to do here.
+ *
+ * Also as we don't care if UV successfully copied over the page in
+ * kvmppc_hmm_migrate_alloc_and_copy(), we don't bother to check
+ * dst_pfn for any errors here.
+ */
+static void
+kvmppc_hmm_migrate_finalize_and_map(struct vm_area_struct *vma,
+ const unsigned long *src_pfn,
+ const unsigned long *dst_pfn,
+ unsigned long start,
+ unsigned long end,
+ void *private)
+{
+}
+
+static const struct migrate_vma_ops kvmppc_hmm_migrate_ops = {
+ .alloc_and_copy = kvmppc_hmm_migrate_alloc_and_copy,
+ .finalize_and_map = kvmppc_hmm_migrate_finalize_and_map,
+};
+
+/*
+ * Move page from normal memory to secure memory.
+ */
+unsigned long
+kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gpa,
+ unsigned long flags, unsigned long page_shift)
+{
+ unsigned long addr, end;
+ unsigned long src_pfn, dst_pfn;
+ struct kvmppc_hmm_migrate_args args;
+ struct vm_area_struct *vma;
+ int srcu_idx;
+ unsigned long gfn = gpa >> page_shift;
+ struct kvm_memory_slot *slot;
+ unsigned long *rmap;
+ int ret = H_SUCCESS;
+
+ if (page_shift != PAGE_SHIFT)
+ return H_P3;
+
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ slot = gfn_to_memslot(kvm, gfn);
+ rmap = &slot->arch.rmap[gfn - slot->base_gfn];
+ addr = gfn_to_hva(kvm, gpa >> page_shift);
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+ if (kvm_is_error_hva(addr))
+ return H_PARAMETER;
+
+ end = addr + (1UL << page_shift);
+
+ if (flags)
+ return H_P2;
+
+ args.rmap = rmap;
+ args.lpid = kvm->arch.lpid;
+ args.gpa = gpa;
+ args.page_shift = page_shift;
+
+ down_read(&kvm->mm->mmap_sem);
+ vma = find_vma_intersection(kvm->mm, addr, end);
+ if (!vma || vma->vm_start > addr || vma->vm_end < end) {
+ ret = H_PARAMETER;
+ goto out;
+ }
+ ret = migrate_vma(&kvmppc_hmm_migrate_ops, vma, addr, end,
+ &src_pfn, &dst_pfn, &args);
+ if (ret < 0)
+ ret = H_PARAMETER;
+out:
+ up_read(&kvm->mm->mmap_sem);
+ return ret;
+}
+
+static void
+kvmppc_hmm_fault_migrate_alloc_and_copy(struct vm_area_struct *vma,
+ const unsigned long *src_pfn,
+ unsigned long *dst_pfn,
+ unsigned long start,
+ unsigned long end,
+ void *private)
+{
+ struct page *dpage, *spage;
+ struct kvmppc_hmm_page_pvt *pvt;
+ unsigned long pfn;
+ int ret = U_SUCCESS;
+
+ *dst_pfn = MIGRATE_PFN_ERROR;
+ spage = migrate_pfn_to_page(*src_pfn);
+ if (!spage || !(*src_pfn & MIGRATE_PFN_MIGRATE))
+ return;
+ if (!is_zone_device_page(spage))
+ return;
+ dpage = hmm_vma_alloc_locked_page(vma, start);
+ if (!dpage)
+ return;
+ pvt = (struct kvmppc_hmm_page_pvt *)
+ hmm_devmem_page_get_drvdata(spage);
+
+ pfn = page_to_pfn(dpage);
+ ret = uv_page_out(pvt->lpid, pfn << PAGE_SHIFT,
+ pvt->gpa, 0, PAGE_SHIFT);
+ if (ret == U_SUCCESS)
+ *dst_pfn = migrate_pfn(pfn) | MIGRATE_PFN_LOCKED;
+}
+
+/*
+ * This migrate_vma() callback is typically used to updated device
+ * page tables after successful migration. We have nothing to do here.
+ */
+static void
+kvmppc_hmm_fault_migrate_finalize_and_map(struct vm_area_struct *vma,
+ const unsigned long *src_pfn,
+ const unsigned long *dst_pfn,
+ unsigned long start,
+ unsigned long end,
+ void *private)
+{
+}
+
+static const struct migrate_vma_ops kvmppc_hmm_fault_migrate_ops = {
+ .alloc_and_copy = kvmppc_hmm_fault_migrate_alloc_and_copy,
+ .finalize_and_map = kvmppc_hmm_fault_migrate_finalize_and_map,
+};
+
+/*
+ * Fault handler callback when HV touches any page that has been
+ * moved to secure memory, we ask UV to give back the page by
+ * issuing a UV_PAGE_OUT uvcall.
+ */
+static vm_fault_t kvmppc_hmm_devmem_fault(struct hmm_devmem *devmem,
+ struct vm_area_struct *vma,
+ unsigned long addr,
+ const struct page *page,
+ unsigned int flags,
+ pmd_t *pmdp)
+{
+ unsigned long end = addr + PAGE_SIZE;
+ unsigned long src_pfn, dst_pfn = 0;
+
+ if (migrate_vma(&kvmppc_hmm_fault_migrate_ops, vma, addr, end,
+ &src_pfn, &dst_pfn, NULL))
+ return VM_FAULT_SIGBUS;
+ if (dst_pfn == MIGRATE_PFN_ERROR)
+ return VM_FAULT_SIGBUS;
+ return 0;
+}
+
+static void kvmppc_hmm_devmem_free(struct hmm_devmem *devmem,
+ struct page *page)
+{
+ kvmppc_hmm_put_page(page);
+}
+
+static const struct hmm_devmem_ops kvmppc_hmm_devmem_ops = {
+ .free = kvmppc_hmm_devmem_free,
+ .fault = kvmppc_hmm_devmem_fault,
+};
+
+/*
+ * Move page from secure memory to normal memory.
+ */
+unsigned long
+kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gpa,
+ unsigned long flags, unsigned long page_shift)
+{
+ unsigned long addr, end;
+ struct vm_area_struct *vma;
+ unsigned long src_pfn, dst_pfn = 0;
+ int srcu_idx;
+ int ret = H_SUCCESS;
+
+ if (page_shift != PAGE_SHIFT)
+ return H_P3;
+
+ if (flags)
+ return H_P2;
+
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ addr = gfn_to_hva(kvm, gpa >> page_shift);
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+ if (kvm_is_error_hva(addr))
+ return H_PARAMETER;
+
+ end = addr + (1UL << page_shift);
+
+ down_read(&kvm->mm->mmap_sem);
+ vma = find_vma_intersection(kvm->mm, addr, end);
+ if (!vma || vma->vm_start > addr || vma->vm_end < end) {
+ ret = H_PARAMETER;
+ goto out;
+ }
+ ret = migrate_vma(&kvmppc_hmm_fault_migrate_ops, vma, addr, end,
+ &src_pfn, &dst_pfn, NULL);
+ if (ret < 0)
+ ret = H_PARAMETER;
+out:
+ up_read(&kvm->mm->mmap_sem);
+ return ret;
+}
+
+static u64 kvmppc_get_secmem_size(void)
+{
+ struct device_node *np;
+ int i, len;
+ const __be32 *prop;
+ u64 size = 0;
+
+ np = of_find_node_by_path("/ibm,ultravisor/ibm,uv-firmware");
+ if (!np)
+ goto out;
+
+ prop = of_get_property(np, "secure-memory-ranges", &len);
+ if (!prop)
+ goto out_put;
+
+ for (i = 0; i < len / (sizeof(*prop) * 4); i++)
+ size += of_read_number(prop + (i * 4) + 2, 2);
+
+out_put:
+ of_node_put(np);
+out:
+ return size;
+}
+
+static int kvmppc_hmm_pages_init(void)
+{
+ unsigned long nr_pfns = kvmppc_hmm.devmem->pfn_last -
+ kvmppc_hmm.devmem->pfn_first;
+
+ kvmppc_hmm.pfn_bitmap = kcalloc(BITS_TO_LONGS(nr_pfns),
+ sizeof(unsigned long), GFP_KERNEL);
+ if (!kvmppc_hmm.pfn_bitmap)
+ return -ENOMEM;
+
+ spin_lock_init(&kvmppc_hmm_lock);
+
+ return 0;
+}
+
+int kvmppc_hmm_init(void)
+{
+ int ret = 0;
+ unsigned long size;
+
+ size = kvmppc_get_secmem_size();
+ if (!size) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ kvmppc_hmm.device = hmm_device_new(NULL);
+ if (IS_ERR(kvmppc_hmm.device)) {
+ ret = PTR_ERR(kvmppc_hmm.device);
+ goto out;
+ }
+
+ kvmppc_hmm.devmem = hmm_devmem_add(&kvmppc_hmm_devmem_ops,
+ &kvmppc_hmm.device->device, size);
+ if (IS_ERR(kvmppc_hmm.devmem)) {
+ ret = PTR_ERR(kvmppc_hmm.devmem);
+ goto out_device;
+ }
+ ret = kvmppc_hmm_pages_init();
+ if (ret < 0)
+ goto out_device;
+
+ pr_info("KVMPPC-HMM: Secure Memory size %lx\n", size);
+ return ret;
+
+out_device:
+ hmm_device_put(kvmppc_hmm.device);
+out:
+ return ret;
+}
+
+void kvmppc_hmm_free(void)
+{
+ kfree(kvmppc_hmm.pfn_bitmap);
+ hmm_device_put(kvmppc_hmm.device);
+}
--
2.17.1
^ permalink raw reply related
* [PATCH v4 2/6] kvmppc: Shared pages support for secure guests
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
In-Reply-To: <20190528064933.23119-1-bharata@linux.ibm.com>
A secure guest will share some of its pages with hypervisor (Eg. virtio
bounce buffers etc). Support shared pages in HMM driver.
Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 3 ++
arch/powerpc/kvm/book3s_hv_hmm.c | 58 +++++++++++++++++++++++++++++--
2 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 2f6b952deb0f..05b8536f6653 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -337,6 +337,9 @@
#define H_TLB_INVALIDATE 0xF808
#define H_COPY_TOFROM_GUEST 0xF80C
+/* Flags for H_SVM_PAGE_IN */
+#define H_PAGE_IN_SHARED 0x1
+
/* Platform-specific hcalls used by the Ultravisor */
#define H_SVM_PAGE_IN 0xEF00
#define H_SVM_PAGE_OUT 0xEF04
diff --git a/arch/powerpc/kvm/book3s_hv_hmm.c b/arch/powerpc/kvm/book3s_hv_hmm.c
index 713806003da3..333829682f59 100644
--- a/arch/powerpc/kvm/book3s_hv_hmm.c
+++ b/arch/powerpc/kvm/book3s_hv_hmm.c
@@ -45,6 +45,7 @@ struct kvmppc_hmm_page_pvt {
unsigned long *rmap;
unsigned int lpid;
unsigned long gpa;
+ bool skip_page_out;
};
struct kvmppc_hmm_migrate_args {
@@ -212,6 +213,45 @@ static const struct migrate_vma_ops kvmppc_hmm_migrate_ops = {
.finalize_and_map = kvmppc_hmm_migrate_finalize_and_map,
};
+/*
+ * Shares the page with HV, thus making it a normal page.
+ *
+ * - If the page is already secure, then provision a new page and share
+ * - If the page is a normal page, share the existing page
+ *
+ * In the former case, uses the HMM fault handler to release the HMM page.
+ */
+static unsigned long
+kvmppc_share_page(struct kvm *kvm, unsigned long *rmap, unsigned long gpa,
+ unsigned long addr, unsigned long page_shift)
+{
+
+ int ret;
+ unsigned int lpid = kvm->arch.lpid;
+ struct page *hmm_page;
+ struct kvmppc_hmm_page_pvt *pvt;
+ unsigned long pfn;
+ int srcu_idx;
+
+ if (kvmppc_is_hmm_pfn(*rmap)) {
+ hmm_page = pfn_to_page(*rmap & ~KVMPPC_PFN_HMM);
+ pvt = (struct kvmppc_hmm_page_pvt *)
+ hmm_devmem_page_get_drvdata(hmm_page);
+ pvt->skip_page_out = true;
+ }
+
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ pfn = gfn_to_pfn(kvm, gpa >> page_shift);
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+ if (is_error_noslot_pfn(pfn))
+ return H_PARAMETER;
+
+ ret = uv_page_in(lpid, pfn << page_shift, gpa, 0, page_shift);
+ kvm_release_pfn_clean(pfn);
+
+ return (ret == U_SUCCESS) ? H_SUCCESS : H_PARAMETER;
+}
+
/*
* Move page from normal memory to secure memory.
*/
@@ -242,9 +282,12 @@ kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gpa,
end = addr + (1UL << page_shift);
- if (flags)
+ if (flags & ~H_PAGE_IN_SHARED)
return H_P2;
+ if (flags & H_PAGE_IN_SHARED)
+ return kvmppc_share_page(kvm, rmap, gpa, addr, page_shift);
+
args.rmap = rmap;
args.lpid = kvm->arch.lpid;
args.gpa = gpa;
@@ -291,8 +334,17 @@ kvmppc_hmm_fault_migrate_alloc_and_copy(struct vm_area_struct *vma,
hmm_devmem_page_get_drvdata(spage);
pfn = page_to_pfn(dpage);
- ret = uv_page_out(pvt->lpid, pfn << PAGE_SHIFT,
- pvt->gpa, 0, PAGE_SHIFT);
+
+ /*
+ * This same alloc_and_copy() callback is used in two cases:
+ * - When HV touches a secure page, for which we do page-out
+ * - When a secure page is converted to shared page, we touch
+ * the page to essentially discard the HMM page. In this case we
+ * skip page-out.
+ */
+ if (!pvt->skip_page_out)
+ ret = uv_page_out(pvt->lpid, pfn << PAGE_SHIFT,
+ pvt->gpa, 0, PAGE_SHIFT);
if (ret == U_SUCCESS)
*dst_pfn = migrate_pfn(pfn) | MIGRATE_PFN_LOCKED;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v4 3/6] kvmppc: H_SVM_INIT_START and H_SVM_INIT_DONE hcalls
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
In-Reply-To: <20190528064933.23119-1-bharata@linux.ibm.com>
H_SVM_INIT_START: Initiate securing a VM
H_SVM_INIT_DONE: Conclude securing a VM
As part of H_SVM_INIT_START register all existing memslots with the UV.
H_SVM_INIT_DONE call by UV informs HV that transition of the guest
to secure mode is complete.
Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 2 ++
arch/powerpc/include/asm/kvm_book3s_hmm.h | 12 ++++++++
arch/powerpc/include/asm/kvm_host.h | 4 +++
arch/powerpc/include/asm/ultravisor-api.h | 1 +
arch/powerpc/include/asm/ultravisor.h | 9 ++++++
arch/powerpc/kvm/book3s_hv.c | 7 +++++
arch/powerpc/kvm/book3s_hv_hmm.c | 34 +++++++++++++++++++++++
7 files changed, 69 insertions(+)
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 05b8536f6653..fa7695928e30 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -343,6 +343,8 @@
/* Platform-specific hcalls used by the Ultravisor */
#define H_SVM_PAGE_IN 0xEF00
#define H_SVM_PAGE_OUT 0xEF04
+#define H_SVM_INIT_START 0xEF08
+#define H_SVM_INIT_DONE 0xEF0C
/* Values for 2nd argument to H_SET_MODE */
#define H_SET_MODE_RESOURCE_SET_CIABR 1
diff --git a/arch/powerpc/include/asm/kvm_book3s_hmm.h b/arch/powerpc/include/asm/kvm_book3s_hmm.h
index 21f3de5f2acb..3e13dab7f690 100644
--- a/arch/powerpc/include/asm/kvm_book3s_hmm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_hmm.h
@@ -11,6 +11,8 @@ extern unsigned long kvmppc_h_svm_page_out(struct kvm *kvm,
unsigned long gra,
unsigned long flags,
unsigned long page_shift);
+extern unsigned long kvmppc_h_svm_init_start(struct kvm *kvm);
+extern unsigned long kvmppc_h_svm_init_done(struct kvm *kvm);
#else
static inline unsigned long
kvmppc_h_svm_page_in(struct kvm *kvm, unsigned long gra,
@@ -25,5 +27,15 @@ kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gra,
{
return H_UNSUPPORTED;
}
+
+static inine unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
+{
+ return H_UNSUPPORTED;
+}
+
+static inine unsigned long kvmppc_h_svm_init_done(struct kvm *kvm);
+{
+ return H_UNSUPPORTED;
+}
#endif /* CONFIG_PPC_UV */
#endif /* __POWERPC_KVM_PPC_HMM_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index c0c9c3455ac4..845fd2a73506 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -272,6 +272,10 @@ struct kvm_hpt_info {
struct kvm_resize_hpt;
+/* Flag values for kvm_arch.secure_guest */
+#define KVMPPC_SECURE_INIT_START 0x1 /* H_SVM_INIT_START has been called */
+#define KVMPPC_SECURE_INIT_DONE 0x2 /* H_SVM_INIT_DONE completed */
+
struct kvm_arch {
unsigned int lpid;
unsigned int smt_mode; /* # vcpus per virtual core */
diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
index 51c4e0b5d197..05b17f4351f4 100644
--- a/arch/powerpc/include/asm/ultravisor-api.h
+++ b/arch/powerpc/include/asm/ultravisor-api.h
@@ -20,6 +20,7 @@
/* opcodes */
#define UV_WRITE_PATE 0xF104
#define UV_RETURN 0xF11C
+#define UV_REGISTER_MEM_SLOT 0xF120
#define UV_PAGE_IN 0xF128
#define UV_PAGE_OUT 0xF12C
diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
index 1e4c51799b43..9befa6fea8db 100644
--- a/arch/powerpc/include/asm/ultravisor.h
+++ b/arch/powerpc/include/asm/ultravisor.h
@@ -61,6 +61,15 @@ static inline int uv_page_out(u64 lpid, u64 dst_ra, u64 src_gpa, u64 flags,
return ucall(UV_PAGE_OUT, retbuf, lpid, dst_ra, src_gpa, flags,
page_shift);
}
+
+static inline int uv_register_mem_slot(u64 lpid, u64 start_gpa, u64 size,
+ u64 flags, u64 slotid)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_REGISTER_MEM_SLOT, retbuf, lpid, start_gpa,
+ size, flags, slotid);
+}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 2918616198de..3683e517541f 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1098,6 +1098,13 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
kvmppc_get_gpr(vcpu, 5),
kvmppc_get_gpr(vcpu, 6));
break;
+ case H_SVM_INIT_START:
+ ret = kvmppc_h_svm_init_start(vcpu->kvm);
+ break;
+ case H_SVM_INIT_DONE:
+ ret = kvmppc_h_svm_init_done(vcpu->kvm);
+ break;
+
default:
return RESUME_HOST;
}
diff --git a/arch/powerpc/kvm/book3s_hv_hmm.c b/arch/powerpc/kvm/book3s_hv_hmm.c
index 333829682f59..18fec814401d 100644
--- a/arch/powerpc/kvm/book3s_hv_hmm.c
+++ b/arch/powerpc/kvm/book3s_hv_hmm.c
@@ -55,6 +55,40 @@ struct kvmppc_hmm_migrate_args {
unsigned long page_shift;
};
+unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
+{
+ struct kvm_memslots *slots;
+ struct kvm_memory_slot *memslot;
+ int ret = H_SUCCESS;
+ int srcu_idx;
+
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ slots = kvm_memslots(kvm);
+ kvm_for_each_memslot(memslot, slots) {
+ ret = uv_register_mem_slot(kvm->arch.lpid,
+ memslot->base_gfn << PAGE_SHIFT,
+ memslot->npages * PAGE_SIZE,
+ 0, memslot->id);
+ if (ret < 0) {
+ ret = H_PARAMETER;
+ goto out;
+ }
+ }
+ kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_START;
+out:
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+ return ret;
+}
+
+unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
+{
+ if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START))
+ return H_UNSUPPORTED;
+
+ kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_DONE;
+ return H_SUCCESS;
+}
+
#define KVMPPC_PFN_HMM (0x1ULL << 61)
static inline bool kvmppc_is_hmm_pfn(unsigned long pfn)
--
2.17.1
^ permalink raw reply related
* [PATCH v4 4/6] kvmppc: Handle memory plug/unplug to secure VM
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
In-Reply-To: <20190528064933.23119-1-bharata@linux.ibm.com>
Register the new memslot with UV during plug and unregister
the memslot during unplug.
Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
---
arch/powerpc/include/asm/ultravisor-api.h | 1 +
arch/powerpc/include/asm/ultravisor.h | 7 +++++++
arch/powerpc/kvm/book3s_hv.c | 19 +++++++++++++++++++
3 files changed, 27 insertions(+)
diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
index 05b17f4351f4..35b71e01177d 100644
--- a/arch/powerpc/include/asm/ultravisor-api.h
+++ b/arch/powerpc/include/asm/ultravisor-api.h
@@ -21,6 +21,7 @@
#define UV_WRITE_PATE 0xF104
#define UV_RETURN 0xF11C
#define UV_REGISTER_MEM_SLOT 0xF120
+#define UV_UNREGISTER_MEM_SLOT 0xF124
#define UV_PAGE_IN 0xF128
#define UV_PAGE_OUT 0xF12C
diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
index 9befa6fea8db..5113457c4743 100644
--- a/arch/powerpc/include/asm/ultravisor.h
+++ b/arch/powerpc/include/asm/ultravisor.h
@@ -70,6 +70,13 @@ static inline int uv_register_mem_slot(u64 lpid, u64 start_gpa, u64 size,
return ucall(UV_REGISTER_MEM_SLOT, retbuf, lpid, start_gpa,
size, flags, slotid);
}
+
+static inline int uv_unregister_mem_slot(u64 lpid, u64 slotid)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_UNREGISTER_MEM_SLOT, retbuf, lpid, slotid);
+}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 3683e517541f..5ef35e230453 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -78,6 +78,7 @@
#include <asm/firmware.h>
#include <asm/kvm_host.h>
#include <asm/kvm_book3s_hmm.h>
+#include <asm/ultravisor.h>
#include "book3s.h"
@@ -4498,6 +4499,24 @@ static void kvmppc_core_commit_memory_region_hv(struct kvm *kvm,
if (change == KVM_MR_FLAGS_ONLY && kvm_is_radix(kvm) &&
((new->flags ^ old->flags) & KVM_MEM_LOG_DIRTY_PAGES))
kvmppc_radix_flush_memslot(kvm, old);
+ /*
+ * If UV hasn't yet called H_SVM_INIT_START, don't register memslots.
+ */
+ if (!kvm->arch.secure_guest)
+ return;
+
+ /*
+ * TODO: Handle KVM_MR_MOVE
+ */
+ if (change == KVM_MR_CREATE) {
+ uv_register_mem_slot(kvm->arch.lpid,
+ new->base_gfn << PAGE_SHIFT,
+ new->npages * PAGE_SIZE,
+ 0,
+ new->id);
+ } else if (change == KVM_MR_DELETE) {
+ uv_unregister_mem_slot(kvm->arch.lpid, old->id);
+ }
}
/*
--
2.17.1
^ permalink raw reply related
* [RFC PATCH v4 5/6] kvmppc: Radix changes for secure guest
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
In-Reply-To: <20190528064933.23119-1-bharata@linux.ibm.com>
- After the guest becomes secure, when we handle a page fault of a page
belonging to SVM in HV, send that page to UV via UV_PAGE_IN.
- Whenever a page is unmapped on the HV side, inform UV via UV_PAGE_INVAL.
Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
---
arch/powerpc/include/asm/kvm_host.h | 13 +++++++++++++
arch/powerpc/include/asm/ultravisor-api.h | 1 +
arch/powerpc/include/asm/ultravisor.h | 7 +++++++
arch/powerpc/kvm/book3s_64_mmu_radix.c | 19 +++++++++++++++++++
arch/powerpc/kvm/book3s_hv_hmm.c | 23 +++++++++++++++++++++++
5 files changed, 63 insertions(+)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 845fd2a73506..63d56f7a357e 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -866,6 +866,8 @@ static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
extern int kvmppc_hmm_init(void);
extern void kvmppc_hmm_free(void);
extern void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free);
+extern bool kvmppc_is_guest_secure(struct kvm *kvm);
+extern int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gpa);
#else
static inline int kvmppc_hmm_init(void)
{
@@ -874,6 +876,17 @@ static inline int kvmppc_hmm_init(void)
static inline void kvmppc_hmm_free(void) {}
static inline void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free) {}
+
+
+static inline bool kvmppc_is_guest_secure(struct kvm *kvm)
+{
+ return false;
+}
+
+static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gpa)
+{
+ return -EFAULT;
+}
#endif /* CONFIG_PPC_UV */
#endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
index 35b71e01177d..eaca65ea2070 100644
--- a/arch/powerpc/include/asm/ultravisor-api.h
+++ b/arch/powerpc/include/asm/ultravisor-api.h
@@ -24,5 +24,6 @@
#define UV_UNREGISTER_MEM_SLOT 0xF124
#define UV_PAGE_IN 0xF128
#define UV_PAGE_OUT 0xF12C
+#define UV_PAGE_INVAL 0xF138
#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
index 5113457c4743..28dbc0f0eddb 100644
--- a/arch/powerpc/include/asm/ultravisor.h
+++ b/arch/powerpc/include/asm/ultravisor.h
@@ -77,6 +77,13 @@ static inline int uv_unregister_mem_slot(u64 lpid, u64 slotid)
return ucall(UV_UNREGISTER_MEM_SLOT, retbuf, lpid, slotid);
}
+
+static inline int uv_page_inval(u64 lpid, u64 gpa, u64 page_shift)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_PAGE_INVAL, retbuf, lpid, gpa, page_shift);
+}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index f55ef071883f..e5d63449ad77 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -21,6 +21,8 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/pte-walk.h>
+#include <asm/ultravisor.h>
+#include <asm/kvm_host.h>
/*
* Supported radix tree geometry.
@@ -923,6 +925,9 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (!(dsisr & DSISR_PRTABLE_FAULT))
gpa |= ea & 0xfff;
+ if (kvmppc_is_guest_secure(kvm))
+ return kvmppc_send_page_to_uv(kvm, gpa & PAGE_MASK);
+
/* Get the corresponding memslot */
memslot = gfn_to_memslot(kvm, gfn);
@@ -980,6 +985,11 @@ int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
unsigned long gpa = gfn << PAGE_SHIFT;
unsigned int shift;
+ if (kvmppc_is_guest_secure(kvm)) {
+ uv_page_inval(kvm->arch.lpid, gpa, PAGE_SIZE);
+ return 0;
+ }
+
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
if (ptep && pte_present(*ptep))
kvmppc_unmap_pte(kvm, ptep, gpa, shift, memslot,
@@ -997,6 +1007,9 @@ int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
int ref = 0;
unsigned long old, *rmapp;
+ if (kvmppc_is_guest_secure(kvm))
+ return ref;
+
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
if (ptep && pte_present(*ptep) && pte_young(*ptep)) {
old = kvmppc_radix_update_pte(kvm, ptep, _PAGE_ACCESSED, 0,
@@ -1021,6 +1034,9 @@ int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot,
unsigned int shift;
int ref = 0;
+ if (kvmppc_is_guest_secure(kvm))
+ return ref;
+
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
if (ptep && pte_present(*ptep) && pte_young(*ptep))
ref = 1;
@@ -1038,6 +1054,9 @@ static int kvm_radix_test_clear_dirty(struct kvm *kvm,
int ret = 0;
unsigned long old, *rmapp;
+ if (kvmppc_is_guest_secure(kvm))
+ return ret;
+
ptep = __find_linux_pte(kvm->arch.pgtable, gpa, NULL, &shift);
if (ptep && pte_present(*ptep) && pte_dirty(*ptep)) {
ret = 1;
diff --git a/arch/powerpc/kvm/book3s_hv_hmm.c b/arch/powerpc/kvm/book3s_hv_hmm.c
index 18fec814401d..a0d47fc140b6 100644
--- a/arch/powerpc/kvm/book3s_hv_hmm.c
+++ b/arch/powerpc/kvm/book3s_hv_hmm.c
@@ -55,6 +55,11 @@ struct kvmppc_hmm_migrate_args {
unsigned long page_shift;
};
+bool kvmppc_is_guest_secure(struct kvm *kvm)
+{
+ return !!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE);
+}
+
unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
{
struct kvm_memslots *slots;
@@ -478,6 +483,24 @@ kvmppc_h_svm_page_out(struct kvm *kvm, unsigned long gpa,
return ret;
}
+int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gpa)
+{
+ int srcu_idx;
+ unsigned long pfn;
+ int ret;
+
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ pfn = gfn_to_pfn(kvm, gpa >> PAGE_SHIFT);
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+ if (is_error_noslot_pfn(pfn))
+ return -EFAULT;
+
+ ret = uv_page_in(kvm->arch.lpid, pfn << PAGE_SHIFT, gpa, 0, PAGE_SHIFT);
+ kvm_release_pfn_clean(pfn);
+
+ return (ret == U_SUCCESS) ? RESUME_GUEST : -EFAULT;
+}
+
static u64 kvmppc_get_secmem_size(void)
{
struct device_node *np;
--
2.17.1
^ permalink raw reply related
* [RFC PATCH v4 6/6] kvmppc: Support reset of secure guest
From: Bharata B Rao @ 2019-05-28 6:49 UTC (permalink / raw)
To: linuxppc-dev
Cc: linuxram, cclaudio, kvm-ppc, Bharata B Rao, linux-mm, jglisse,
aneesh.kumar, paulus, sukadev
In-Reply-To: <20190528064933.23119-1-bharata@linux.ibm.com>
Add support for reset of secure guest via a new ioctl KVM_PPC_SVM_OFF.
This ioctl will be issued by QEMU during reset and in this ioctl,
we ask UV to terminate the guest via UV_SVM_TERMINATE ucall,
reinitialize guest's partitioned scoped page tables and release all
HMM pages of the secure guest.
After these steps, guest is ready to issue UV_ESM call once again
to switch to secure mode.
Signed-off-by: Bharata B Rao <bharata@linux.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
[Implementation of uv_svm_terminate() and its call from
guest shutdown path]
---
arch/powerpc/include/asm/kvm_host.h | 6 ++
arch/powerpc/include/asm/kvm_ppc.h | 4 ++
arch/powerpc/include/asm/ultravisor-api.h | 1 +
arch/powerpc/include/asm/ultravisor.h | 7 ++
arch/powerpc/kvm/book3s_hv.c | 23 +++++++
arch/powerpc/kvm/book3s_hv_hmm.c | 83 +++++++++++++++++++++++
arch/powerpc/kvm/powerpc.c | 12 ++++
include/uapi/linux/kvm.h | 1 +
tools/include/uapi/linux/kvm.h | 1 +
9 files changed, 138 insertions(+)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 63d56f7a357e..c220bcfe7726 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -868,6 +868,7 @@ extern void kvmppc_hmm_free(void);
extern void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free);
extern bool kvmppc_is_guest_secure(struct kvm *kvm);
extern int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gpa);
+extern int kvmppc_hmm_svm_off(struct kvm *kvm);
#else
static inline int kvmppc_hmm_init(void)
{
@@ -887,6 +888,11 @@ static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gpa)
{
return -EFAULT;
}
+
+static inline int kvmppc_hmm_svm_off(struct kvm *kvm)
+{
+ return 0;
+}
#endif /* CONFIG_PPC_UV */
#endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index bc892380e6cd..aee4b81e9558 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -188,6 +188,7 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
extern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm);
extern int kvmppc_switch_mmu_to_radix(struct kvm *kvm);
extern void kvmppc_setup_partition_table(struct kvm *kvm);
+extern int kvmppc_reinit_partition_table(struct kvm *kvm);
extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
struct kvm_create_spapr_tce_64 *args);
@@ -332,6 +333,7 @@ struct kvmppc_ops {
int size);
int (*store_to_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
int size);
+ int (*svm_off)(struct kvm *kvm);
};
extern struct kvmppc_ops *kvmppc_hv_ops;
@@ -961,5 +963,7 @@ static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
}
extern void xics_wake_cpu(int cpu);
+extern void kvmppc_hmm_free_memslot_pfns(struct kvm *kvm,
+ struct kvm_memslots *slots);
#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/ultravisor-api.h b/arch/powerpc/include/asm/ultravisor-api.h
index eaca65ea2070..6d59c64f30ce 100644
--- a/arch/powerpc/include/asm/ultravisor-api.h
+++ b/arch/powerpc/include/asm/ultravisor-api.h
@@ -25,5 +25,6 @@
#define UV_PAGE_IN 0xF128
#define UV_PAGE_OUT 0xF12C
#define UV_PAGE_INVAL 0xF138
+#define UV_SVM_TERMINATE 0xF13C
#endif /* _ASM_POWERPC_ULTRAVISOR_API_H */
diff --git a/arch/powerpc/include/asm/ultravisor.h b/arch/powerpc/include/asm/ultravisor.h
index 28dbc0f0eddb..1c60b7328f09 100644
--- a/arch/powerpc/include/asm/ultravisor.h
+++ b/arch/powerpc/include/asm/ultravisor.h
@@ -84,6 +84,13 @@ static inline int uv_page_inval(u64 lpid, u64 gpa, u64 page_shift)
return ucall(UV_PAGE_INVAL, retbuf, lpid, gpa, page_shift);
}
+
+static inline int uv_svm_terminate(u64 lpid)
+{
+ unsigned long retbuf[UCALL_BUFSIZE];
+
+ return ucall(UV_SVM_TERMINATE, retbuf, lpid);
+}
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_ULTRAVISOR_H */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 5ef35e230453..4a423c92fb18 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4571,6 +4571,22 @@ void kvmppc_setup_partition_table(struct kvm *kvm)
kvmhv_set_ptbl_entry(kvm->arch.lpid, dw0, dw1);
}
+/*
+ * Called from KVM_PPC_SVM_OFF ioctl at guest reset time when secure
+ * guest is converted back to normal guest.
+ */
+int kvmppc_reinit_partition_table(struct kvm *kvm)
+{
+ int ret;
+
+ ret = kvmppc_init_vm_radix(kvm);
+ if (ret)
+ return ret;
+
+ kvmppc_setup_partition_table(kvm);
+ return 0;
+}
+
/*
* Set up HPT (hashed page table) and RMA (real-mode area).
* Must be called with kvm->lock held.
@@ -4950,6 +4966,7 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
if (nesting_enabled(kvm))
kvmhv_release_all_nested(kvm);
kvm->arch.process_table = 0;
+ uv_svm_terminate(kvm->arch.lpid);
kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0);
}
kvmppc_free_lpid(kvm->arch.lpid);
@@ -5391,6 +5408,11 @@ static int kvmhv_store_to_eaddr(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
return rc;
}
+static int kvmhv_svm_off(struct kvm *kvm)
+{
+ return kvmppc_hmm_svm_off(kvm);
+}
+
static struct kvmppc_ops kvm_ops_hv = {
.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
@@ -5433,6 +5455,7 @@ static struct kvmppc_ops kvm_ops_hv = {
.enable_nested = kvmhv_enable_nested,
.load_from_eaddr = kvmhv_load_from_eaddr,
.store_to_eaddr = kvmhv_store_to_eaddr,
+ .svm_off = kvmhv_svm_off,
};
static int kvm_init_subcore_bitmap(void)
diff --git a/arch/powerpc/kvm/book3s_hv_hmm.c b/arch/powerpc/kvm/book3s_hv_hmm.c
index a0d47fc140b6..c9ce8b003ef5 100644
--- a/arch/powerpc/kvm/book3s_hv_hmm.c
+++ b/arch/powerpc/kvm/book3s_hv_hmm.c
@@ -31,6 +31,8 @@
#include <linux/kvm_host.h>
#include <linux/sched/mm.h>
#include <asm/ultravisor.h>
+#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s.h>
struct kvmppc_hmm_device {
struct hmm_device *device;
@@ -60,6 +62,30 @@ bool kvmppc_is_guest_secure(struct kvm *kvm)
return !!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE);
}
+int kvmppc_hmm_svm_off(struct kvm *kvm)
+{
+ int ret = 0;
+ int i;
+
+ if (kvmppc_is_guest_secure(kvm)) {
+ ret = uv_svm_terminate(kvm->arch.lpid);
+ if (ret != U_SUCCESS) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kvmppc_reinit_partition_table(kvm);
+ if (ret)
+ goto out;
+ kvm->arch.secure_guest = 0;
+ for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
+ kvmppc_hmm_free_memslot_pfns(kvm,
+ __kvm_memslots(kvm, i));
+ }
+out:
+ return ret;
+}
+
unsigned long kvmppc_h_svm_init_start(struct kvm *kvm)
{
struct kvm_memslots *slots;
@@ -91,6 +117,11 @@ unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
return H_UNSUPPORTED;
kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_DONE;
+ if (kvm_is_radix(kvm)) {
+ pr_info("Guest went secure, freeing HV side radix pgtables\n");
+ kvmppc_free_radix(kvm);
+ }
+
return H_SUCCESS;
}
@@ -113,6 +144,58 @@ void kvmppc_hmm_release_pfns(struct kvm_memory_slot *free)
}
}
+/*
+ * Drop HMM pages that we maintain for the secure guest
+ *
+ * We mark the pages to be skipped from UV_PAGE_OUT when there is HMM
+ * fault on these pages. Next we get these pages, force HMM fault,
+ * do fault migration to replace the HMM PTEs from QEMU page tables
+ * with normal PTEs from newly allocated pages.
+ */
+static void kvmppc_hmm_drop_pages(struct kvm_memory_slot *free, struct kvm *kvm)
+{
+ int i;
+ struct kvmppc_hmm_page_pvt *pvt;
+ unsigned long pfn;
+
+ for (i = 0; i < free->npages; i++) {
+ unsigned long *rmap = &free->arch.rmap[i];
+ struct page *hmm_page;
+
+ if (kvmppc_is_hmm_pfn(*rmap)) {
+ hmm_page = pfn_to_page(*rmap & ~KVMPPC_PFN_HMM);
+ pvt = (struct kvmppc_hmm_page_pvt *)
+ hmm_devmem_page_get_drvdata(hmm_page);
+ pvt->skip_page_out = true;
+
+ pfn = gfn_to_pfn(kvm, pvt->gpa >> PAGE_SHIFT);
+ if (is_error_noslot_pfn(pfn))
+ continue;
+ kvm_release_pfn_clean(pfn);
+ }
+ }
+}
+
+/*
+ * Called from KVM_PPC_SVM_OFF ioctl when secure guest is reset
+ *
+ * UV has already cleaned up the guest, we release any HMM pages that
+ * we maintain
+ */
+void kvmppc_hmm_free_memslot_pfns(struct kvm *kvm, struct kvm_memslots *slots)
+{
+ struct kvm_memory_slot *memslot;
+ int srcu_idx;
+
+ if (!slots)
+ return;
+
+ srcu_idx = srcu_read_lock(&kvm->srcu);
+ kvm_for_each_memslot(memslot, slots)
+ kvmppc_hmm_drop_pages(memslot, kvm);
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+}
+
/*
* Get a free HMM PFN from the pool
*
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 3393b166817a..0c5fae004adf 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -42,6 +42,8 @@
#include <asm/hvcall.h>
#include <asm/plpar_wrappers.h>
#endif
+#include <asm/ultravisor.h>
+#include <asm/kvm_host.h>
#include "timing.h"
#include "irq.h"
@@ -2423,6 +2425,16 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = -EFAULT;
break;
}
+ case KVM_PPC_SVM_OFF: {
+ struct kvm *kvm = filp->private_data;
+
+ r = 0;
+ if (!kvm->arch.kvm_ops->svm_off)
+ goto out;
+
+ r = kvm->arch.kvm_ops->svm_off(kvm);
+ break;
+ }
default: {
struct kvm *kvm = filp->private_data;
r = kvm->arch.kvm_ops->arch_vm_ioctl(filp, ioctl, arg);
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 2fe12b40d503..c1dbdd428025 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1327,6 +1327,7 @@ struct kvm_s390_ucas_mapping {
#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
/* Available with KVM_CAP_PPC_GET_CPU_CHAR */
#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
+#define KVM_PPC_SVM_OFF _IO(KVMIO, 0xb2)
/* ioctl for vm fd */
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 6d4ea4b6c922..03c89f4a01b2 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -1319,6 +1319,7 @@ struct kvm_s390_ucas_mapping {
#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
/* Available with KVM_CAP_PPC_GET_CPU_CHAR */
#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
+#define KVM_PPC_SVM_OFF _IO(KVMIO, 0xb2)
/* ioctl for vm fd */
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v3 1/3] PCI: Introduce pcibios_ignore_alignment_request
From: Shawn Anastasio @ 2019-05-28 7:39 UTC (permalink / raw)
To: Alexey Kardashevskiy, Oliver
Cc: Sam Bobroff, linux-pci, Linux Kernel Mailing List, rppt,
Paul Mackerras, Bjorn Helgaas, xyjxie, linuxppc-dev
In-Reply-To: <b0a38504-24c3-77bc-b308-7b498f07760a@ozlabs.ru>
On 5/28/19 1:27 AM, Alexey Kardashevskiy wrote:
>
>
> On 28/05/2019 15:36, Oliver wrote:
>> On Tue, May 28, 2019 at 2:03 PM Shawn Anastasio <shawn@anastas.io> wrote:
>>>
>>> Introduce a new pcibios function pcibios_ignore_alignment_request
>>> which allows the PCI core to defer to platform-specific code to
>>> determine whether or not to ignore alignment requests for PCI resources.
>>>
>>> The existing behavior is to simply ignore alignment requests when
>>> PCI_PROBE_ONLY is set. This is behavior is maintained by the
>>> default implementation of pcibios_ignore_alignment_request.
>>>
>>> Signed-off-by: Shawn Anastasio <shawn@anastas.io>
>>> ---
>>> drivers/pci/pci.c | 9 +++++++--
>>> include/linux/pci.h | 1 +
>>> 2 files changed, 8 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>> index 8abc843b1615..8207a09085d1 100644
>>> --- a/drivers/pci/pci.c
>>> +++ b/drivers/pci/pci.c
>>> @@ -5882,6 +5882,11 @@ resource_size_t __weak pcibios_default_alignment(void)
>>> return 0;
>>> }
>>>
>>> +int __weak pcibios_ignore_alignment_request(void)
>>> +{
>>> + return pci_has_flag(PCI_PROBE_ONLY);
>>> +}
>>> +
>>> #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
>>> static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
>>> static DEFINE_SPINLOCK(resource_alignment_lock);
>>> @@ -5906,9 +5911,9 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
>>> p = resource_alignment_param;
>>> if (!*p && !align)
>>> goto out;
>>> - if (pci_has_flag(PCI_PROBE_ONLY)) {
>>> + if (pcibios_ignore_alignment_request()) {
>>> align = 0;
>>> - pr_info_once("PCI: Ignoring requested alignments (PCI_PROBE_ONLY)\n");
>>> + pr_info_once("PCI: Ignoring requested alignments\n");
>>> goto out;
>>> }
>>
>> I think the logic here is questionable to begin with. If the user has
>> explicitly requested re-aligning a resource via the command line then
>> we should probably do it even if PCI_PROBE_ONLY is set. When it breaks
>> they get to keep the pieces.
>>
>> That said, the real issue here is that PCI_PROBE_ONLY probably
>> shouldn't be set under qemu/kvm. Under the other hypervisor (PowerVM)
>> hotplugged devices are configured by firmware before it's passed to
>> the guest and we need to keep the FW assignments otherwise things
>> break. QEMU however doesn't do any BAR assignments and relies on that
>> being handled by the guest. At boot time this is done by SLOF, but
>> Linux only keeps SLOF around until it's extracted the device-tree.
>> Once that's done SLOF gets blown away and the kernel needs to do it's
>> own BAR assignments. I'm guessing there's a hack in there to make it
>> work today, but it's a little surprising that it works at all...
>
>
> The hack is to run a modified qemu-aware "/usr/sbin/rtas_errd" in the
> guest which receives an event from qemu (RAS_EPOW from
> /proc/interrupts), fetches device tree chunks (and as I understand it -
> they come with BARs from phyp but without from qemu) and writes "1" to
> "/sys/bus/pci/rescan" which calls pci_assign_resource() eventually:
Interesting. Does this mean that the PHYP hotplug path doesn't
call pci_assign_resource? If so it means the patch may not
break that platform after all, though it still may not be
the correct way of doing things.
>
> [c000000006e6f960] [c0000000005f62d4] pci_assign_resource+0x44/0x360
>
> [c000000006e6fa10] [c0000000005f8b54]
> assign_requested_resources_sorted+0x84/0x110
> [c000000006e6fa60] [c0000000005f9540] __assign_resources_sorted+0xd0/0x750
> [c000000006e6fb40] [c0000000005fb2e0]
> __pci_bus_assign_resources+0x80/0x280
> [c000000006e6fc00] [c0000000005fb95c]
> pci_assign_unassigned_bus_resources+0xbc/0x100
> [c000000006e6fc60] [c0000000005e3d74] pci_rescan_bus+0x34/0x60
>
> [c000000006e6fc90] [c0000000005f1ef4] rescan_store+0x84/0xc0
>
> [c000000006e6fcd0] [c00000000068060c] bus_attr_store+0x3c/0x60
>
> [c000000006e6fcf0] [c00000000037853c] sysfs_kf_write+0x5c/0x80
>
>
>
>
>
>>
>> IIRC Sam Bobroff was looking at hotplug under pseries recently so he
>> might have something to add. He's sick at the moment, but I'll ask him
>> to take a look at this once he's back among the living
>>
>>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>>> index 4a5a84d7bdd4..47471dcdbaf9 100644
>>> --- a/include/linux/pci.h
>>> +++ b/include/linux/pci.h
>>> @@ -1990,6 +1990,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) {}
>>> int pcibios_alloc_irq(struct pci_dev *dev);
>>> void pcibios_free_irq(struct pci_dev *dev);
>>> resource_size_t pcibios_default_alignment(void);
>>> +int pcibios_ignore_alignment_request(void);
>>>
>>> #ifdef CONFIG_HIBERNATE_CALLBACKS
>>> extern struct dev_pm_ops pcibios_pm_ops;
>>> --
>>> 2.20.1
>>>
>
^ permalink raw reply
* [PATCH 1/3][V2] lib: fix match_string() helper on -1 array size
From: Alexandru Ardelean @ 2019-05-28 7:39 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, linux-ide, linux-clk,
linux-rpi-kernel, linux-arm-kernel, linux-rockchip, linux-pm,
linux-gpio, dri-devel, intel-gfx, linux-omap, linux-mmc,
linux-wireless, netdev, linux-pci, linux-tegra, devel, linux-usb,
kvm, linux-fbdev, linux-mtd, cgroups, linux-mm,
linux-security-module, linux-integrity, alsa-devel
Cc: gregkh, Alexandru Ardelean, heikki.krogerus, andriy.shevchenko
In-Reply-To: <20190508112842.11654-1-alexandru.ardelean@analog.com>
The documentation the `_match_string()` helper mentions that `n`
should be:
* @n: number of strings in the array or -1 for NULL terminated arrays
The behavior of the function is different, in the sense that it exits on
the first NULL element in the array, regardless of whether `n` is -1 or a
positive number.
This patch changes the behavior, to exit the loop when a NULL element is
found and n == -1. Essentially, this aligns the behavior with the
doc-string.
There are currently many users of `match_string()`, and so, in order to go
through them, the next patches in the series will focus on doing some
cosmetic changes, which are aimed at grouping the users of
`match_string()`.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
Changelog v1 -> v2:
* split the initial series into just 3 patches that fix the
`match_string()` helper and start introducing a new version of this
helper, which computes array-size of static arrays
lib/string.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/string.c b/lib/string.c
index 6016eb3ac73d..e2cf5acc83bd 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -681,8 +681,11 @@ int match_string(const char * const *array, size_t n, const char *string)
for (index = 0; index < n; index++) {
item = array[index];
- if (!item)
+ if (!item) {
+ if (n != (size_t)-1)
+ continue;
break;
+ }
if (!strcmp(item, string))
return index;
}
--
2.20.1
^ permalink raw reply related
* [PATCH 2/3][V2] treewide: rename match_string() -> __match_string()
From: Alexandru Ardelean @ 2019-05-28 7:39 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, linux-ide, linux-clk,
linux-rpi-kernel, linux-arm-kernel, linux-rockchip, linux-pm,
linux-gpio, dri-devel, intel-gfx, linux-omap, linux-mmc,
linux-wireless, netdev, linux-pci, linux-tegra, devel, linux-usb,
kvm, linux-fbdev, linux-mtd, cgroups, linux-mm,
linux-security-module, linux-integrity, alsa-devel
Cc: gregkh, Alexandru Ardelean, heikki.krogerus, andriy.shevchenko
In-Reply-To: <20190528073932.25365-1-alexandru.ardelean@analog.com>
This change does a rename of match_string() -> __match_string().
There are a few parts to the intention here (with this change):
1. Align with sysfs_match_string()/__sysfs_match_string()
2. This helps to group users of `match_string()`:
a. those that use ARRAY_SIZE(_a) to specify the number of elements
b. those that use -1 to pass a NULL terminated array of strings
c. special users, which (after eliminating 1 & 2) are not that many
This change is done treewide. Updates to the new match_string() helper will
be done on a per-subsystem basis, as the cadence of each subsystem differs.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
arch/powerpc/xmon/xmon.c | 2 +-
arch/x86/kernel/cpu/mtrr/if.c | 2 +-
drivers/ata/pata_hpt366.c | 2 +-
drivers/ata/pata_hpt37x.c | 2 +-
drivers/base/devcon.c | 2 +-
drivers/base/property.c | 2 +-
drivers/clk/bcm/clk-bcm2835.c | 6 +++---
drivers/clk/rockchip/clk.c | 4 ++--
drivers/cpufreq/intel_pstate.c | 2 +-
drivers/gpio/gpiolib-of.c | 2 +-
drivers/gpu/drm/drm_edid_load.c | 2 +-
drivers/gpu/drm/drm_panel_orientation_quirks.c | 2 +-
drivers/gpu/drm/i915/intel_pipe_crc.c | 2 +-
drivers/ide/hpt366.c | 2 +-
drivers/mfd/omap-usb-host.c | 2 +-
drivers/mmc/host/sdhci-xenon-phy.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +-
drivers/pci/pcie/aer.c | 2 +-
drivers/phy/tegra/xusb.c | 4 ++--
drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 4 ++--
drivers/pinctrl/pinmux.c | 2 +-
drivers/power/supply/ab8500_btemp.c | 2 +-
drivers/power/supply/ab8500_charger.c | 2 +-
drivers/power/supply/ab8500_fg.c | 2 +-
drivers/power/supply/abx500_chargalg.c | 2 +-
drivers/power/supply/charger-manager.c | 4 ++--
drivers/staging/gdm724x/gdm_tty.c | 4 ++--
drivers/usb/common/common.c | 4 ++--
drivers/usb/typec/class.c | 10 +++++-----
drivers/usb/typec/tps6598x.c | 2 +-
drivers/vfio/vfio.c | 6 +++---
drivers/video/fbdev/pxafb.c | 2 +-
fs/ubifs/auth.c | 4 ++--
include/linux/string.h | 2 +-
kernel/cgroup/rdma.c | 2 +-
kernel/sched/debug.c | 2 +-
kernel/trace/trace.c | 2 +-
lib/string.c | 8 ++++----
mm/mempolicy.c | 2 +-
mm/vmpressure.c | 4 ++--
security/apparmor/lsm.c | 4 ++--
security/integrity/ima/ima_main.c | 2 +-
sound/firewire/oxfw/oxfw.c | 2 +-
sound/pci/oxygen/oxygen_mixer.c | 2 +-
sound/soc/codecs/max98088.c | 2 +-
sound/soc/codecs/max98095.c | 2 +-
sound/soc/soc-dapm.c | 2 +-
47 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 1b0149b2bb6c..8039759a9e82 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -3264,7 +3264,7 @@ scanhex(unsigned long *vp)
regname[i] = c;
}
regname[i] = 0;
- i = match_string(regnames, N_PTREGS, regname);
+ i = __match_string(regnames, N_PTREGS, regname);
if (i < 0) {
printf("invalid register name '%%%s'\n", regname);
return 0;
diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c
index 4d36dcc1cf87..4ec7a5f7b94c 100644
--- a/arch/x86/kernel/cpu/mtrr/if.c
+++ b/arch/x86/kernel/cpu/mtrr/if.c
@@ -142,7 +142,7 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos)
return -EINVAL;
ptr = skip_spaces(ptr + 5);
- i = match_string(mtrr_strings, MTRR_NUM_TYPES, ptr);
+ i = __match_string(mtrr_strings, MTRR_NUM_TYPES, ptr);
if (i < 0)
return i;
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 2574d6fbb1ad..a23ec26cc95f 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -181,7 +181,7 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
- i = match_string(list, -1, model_num);
+ i = __match_string(list, -1, model_num);
if (i >= 0) {
pr_warn("%s is not supported for %s\n", modestr, list[i]);
return 1;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index fad6c6a87313..ac0499e4ae4b 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -229,7 +229,7 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
- i = match_string(list, -1, model_num);
+ i = __match_string(list, -1, model_num);
if (i >= 0) {
pr_warn("%s is not supported for %s\n", modestr, list[i]);
return 1;
diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c
index 04db9ae235e4..7bc1c619b721 100644
--- a/drivers/base/devcon.c
+++ b/drivers/base/devcon.c
@@ -70,7 +70,7 @@ void *device_connection_find_match(struct device *dev, const char *con_id,
mutex_lock(&devcon_lock);
list_for_each_entry(con, &devcon_list, list) {
- ep = match_string(con->endpoint, 2, devname);
+ ep = __match_string(con->endpoint, 2, devname);
if (ep < 0)
continue;
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 348b37e64944..67195d6bfdca 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -443,7 +443,7 @@ int fwnode_property_match_string(const struct fwnode_handle *fwnode,
if (ret < 0)
goto out;
- ret = match_string(values, nval, string);
+ ret = __match_string(values, nval, string);
if (ret < 0)
ret = -ENODATA;
out:
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 770bb01f523e..91bb94d68798 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -1391,9 +1391,9 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
for (i = 0; i < data->num_mux_parents; i++) {
parents[i] = data->parents[i];
- ret = match_string(cprman_parent_names,
- ARRAY_SIZE(cprman_parent_names),
- parents[i]);
+ ret = __match_string(cprman_parent_names,
+ ARRAY_SIZE(cprman_parent_names),
+ parents[i]);
if (ret >= 0)
parents[i] = cprman->real_parent_names[ret];
}
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index d5fac5a8a3d7..2163bb54a663 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -280,8 +280,8 @@ static struct clk *rockchip_clk_register_frac_branch(
struct clk *mux_clk;
int ret;
- frac->mux_frac_idx = match_string(child->parent_names,
- child->num_parents, name);
+ frac->mux_frac_idx = __match_string(child->parent_names,
+ child->num_parents, name);
frac->mux_ops = &clk_mux_ops;
frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 34b54df41aaa..a1f79451308c 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -703,7 +703,7 @@ static ssize_t store_energy_performance_preference(
if (ret != 1)
return -EINVAL;
- ret = match_string(energy_perf_strings, -1, str_preference);
+ ret = __match_string(energy_perf_strings, -1, str_preference);
if (ret < 0)
return ret;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index aec7bd86ae7e..527be82e1bac 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -278,7 +278,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
if (!con_id)
return ERR_PTR(-ENOENT);
- i = match_string(whitelist, ARRAY_SIZE(whitelist), con_id);
+ i = __match_string(whitelist, ARRAY_SIZE(whitelist), con_id);
if (i < 0)
return ERR_PTR(-ENOENT);
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index 1e5593575d23..53c55fc8b8c2 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -174,7 +174,7 @@ static void *edid_load(struct drm_connector *connector, const char *name,
int i, valid_extensions = 0;
bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
- builtin = match_string(generic_edid_name, GENERIC_EDIDS, name);
+ builtin = __match_string(generic_edid_name, GENERIC_EDIDS, name);
if (builtin >= 0) {
fwdata = generic_edid[builtin];
fwsize = sizeof(generic_edid[builtin]);
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
index 521aff99b08a..063553adb22d 100644
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -213,7 +213,7 @@ int drm_get_panel_orientation_quirk(int width, int height)
if (!bios_date)
continue;
- i = match_string(data->bios_dates, -1, bios_date);
+ i = __match_string(data->bios_dates, -1, bios_date);
if (i >= 0)
return data->orientation;
}
diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c
index e7c7be4911c1..3e6af7600c25 100644
--- a/drivers/gpu/drm/i915/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
@@ -440,7 +440,7 @@ display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s)
return 0;
}
- i = match_string(pipe_crc_sources, ARRAY_SIZE(pipe_crc_sources), buf);
+ i = __match_string(pipe_crc_sources, ARRAY_SIZE(pipe_crc_sources), buf);
if (i < 0)
return i;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index fd3b5da44619..5e880a1ebcde 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -534,7 +534,7 @@ static const struct hpt_info hpt371n = {
static bool check_in_drive_list(ide_drive_t *drive, const char **list)
{
- return match_string(list, -1, (char *)&drive->id[ATA_ID_PROD]) >= 0;
+ return __match_string(list, -1, (char *)&drive->id[ATA_ID_PROD]) >= 0;
}
static struct hpt_info *hpt3xx_get_info(struct device *dev)
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 800986a79704..9aaacb5bdb26 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -509,7 +509,7 @@ static int usbhs_omap_get_dt_pdata(struct device *dev,
continue;
/* get 'enum usbhs_omap_port_mode' from port mode string */
- ret = match_string(port_modes, ARRAY_SIZE(port_modes), mode);
+ ret = __match_string(port_modes, ARRAY_SIZE(port_modes), mode);
if (ret < 0) {
dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
i, mode);
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c
index 8d07ee1b8f08..59b7a6cac995 100644
--- a/drivers/mmc/host/sdhci-xenon-phy.c
+++ b/drivers/mmc/host/sdhci-xenon-phy.c
@@ -821,7 +821,7 @@ static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
int ret;
- priv->phy_type = match_string(phy_types, NR_PHY_TYPES, phy_name);
+ priv->phy_type = __match_string(phy_types, NR_PHY_TYPES, phy_name);
if (priv->phy_type < 0) {
dev_err(mmc_dev(host->mmc),
"Unable to determine PHY name %s. Use default eMMC 5.1 PHY\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index d4ff6b44de2c..969f09a56ba7 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -667,7 +667,7 @@ iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
};
int ret, bt_force_ant_mode;
- ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
+ ret = __match_string(modes_str, ARRAY_SIZE(modes_str), buf);
if (ret < 0)
return ret;
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index b45bc47d04fe..02f54802fca0 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -206,7 +206,7 @@ void pcie_ecrc_get_policy(char *str)
{
int i;
- i = match_string(ecrc_policy_str, ARRAY_SIZE(ecrc_policy_str), str);
+ i = __match_string(ecrc_policy_str, ARRAY_SIZE(ecrc_policy_str), str);
if (i < 0)
return;
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index 0417213ed68b..060ba6a0a031 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -119,7 +119,7 @@ int tegra_xusb_lane_parse_dt(struct tegra_xusb_lane *lane,
if (err < 0)
return err;
- err = match_string(lane->soc->funcs, lane->soc->num_funcs, function);
+ err = __match_string(lane->soc->funcs, lane->soc->num_funcs, function);
if (err < 0) {
dev_err(dev, "invalid function \"%s\" for lane \"%pOFn\"\n",
function, np);
@@ -568,7 +568,7 @@ static int tegra_xusb_usb2_port_parse_dt(struct tegra_xusb_usb2_port *usb2)
usb2->internal = of_property_read_bool(np, "nvidia,internal");
if (!of_property_read_string(np, "mode", &mode)) {
- int err = match_string(modes, ARRAY_SIZE(modes), mode);
+ int err = __match_string(modes, ARRAY_SIZE(modes), mode);
if (err < 0) {
dev_err(&port->dev, "invalid value %s for \"mode\"\n",
mode);
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 6462d3ca7ceb..07a5bcaa0067 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -348,7 +348,7 @@ static int armada_37xx_pmx_set_by_name(struct pinctrl_dev *pctldev,
dev_dbg(info->dev, "enable function %s group %s\n",
name, grp->name);
- func = match_string(grp->funcs, NB_FUNCS, name);
+ func = __match_string(grp->funcs, NB_FUNCS, name);
if (func < 0)
return -ENOTSUPP;
@@ -938,7 +938,7 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info)
struct armada_37xx_pin_group *gp = &info->groups[g];
int f;
- f = match_string(gp->funcs, NB_FUNCS, name);
+ f = __match_string(gp->funcs, NB_FUNCS, name);
if (f < 0)
continue;
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 4d0cc1889dd9..041326d0ab7b 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -348,7 +348,7 @@ int pinmux_map_to_setting(const struct pinctrl_map *map,
}
if (map->data.mux.group) {
group = map->data.mux.group;
- ret = match_string(groups, num_groups, group);
+ ret = __match_string(groups, num_groups, group);
if (ret < 0) {
dev_err(pctldev->dev,
"invalid group \"%s\" for function \"%s\"\n",
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index 708fd58cd62b..1cf3b43a41e4 100644
--- a/drivers/power/supply/ab8500_btemp.c
+++ b/drivers/power/supply/ab8500_btemp.c
@@ -858,7 +858,7 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
* For all psy where the name of your driver
* appears in any supplied_to
*/
- j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
+ j = __match_string(supplicants, ext->num_supplicants, psy->desc->name);
if (j < 0)
return 0;
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index 98b335042ba6..8094f38e4085 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -1876,7 +1876,7 @@ static int ab8500_charger_get_ext_psy_data(struct device *dev, void *data)
di = to_ab8500_charger_usb_device_info(usb_chg);
/* For all psy where the driver name appears in any supplied_to */
- j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
+ j = __match_string(supplicants, ext->num_supplicants, psy->desc->name);
if (j < 0)
return 0;
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 776102c31305..408339c5a4a8 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2174,7 +2174,7 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
* For all psy where the name of your driver
* appears in any supplied_to
*/
- j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
+ j = __match_string(supplicants, ext->num_supplicants, psy->desc->name);
if (j < 0)
return 0;
diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c
index 947709cdd14e..b2fcd0ba379d 100644
--- a/drivers/power/supply/abx500_chargalg.c
+++ b/drivers/power/supply/abx500_chargalg.c
@@ -946,7 +946,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
psy = (struct power_supply *)data;
di = power_supply_get_drvdata(psy);
/* For all psy where the driver name appears in any supplied_to */
- j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
+ j = __match_string(supplicants, ext->num_supplicants, psy->desc->name);
if (j < 0)
return 0;
diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
index a6900aa0d2ed..70e758e4f4f4 100644
--- a/drivers/power/supply/charger-manager.c
+++ b/drivers/power/supply/charger-manager.c
@@ -2022,8 +2022,8 @@ void cm_notify_event(struct power_supply *psy, enum cm_event_types type,
mutex_lock(&cm_list_mtx);
list_for_each_entry(cm, &cm_list, entry) {
- if (match_string(cm->desc->psy_charger_stat, -1,
- psy->desc->name) >= 0) {
+ if (__match_string(cm->desc->psy_charger_stat, -1,
+ psy->desc->name) >= 0) {
found_power_supply = true;
break;
}
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
index 6e813693a766..6e147a324652 100644
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -56,8 +56,8 @@ static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
struct gdm *gdm = NULL;
int ret;
- ret = match_string(DRIVER_STRING, TTY_MAX_COUNT,
- tty->driver->driver_name);
+ ret = __match_string(DRIVER_STRING, TTY_MAX_COUNT,
+ tty->driver->driver_name);
if (ret < 0)
return -ENODEV;
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 18f5dcf58b0d..97f87d758e8a 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -84,7 +84,7 @@ enum usb_device_speed usb_get_maximum_speed(struct device *dev)
if (ret < 0)
return USB_SPEED_UNKNOWN;
- ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
+ ret = __match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
}
@@ -122,7 +122,7 @@ static enum usb_dr_mode usb_get_dr_mode_from_string(const char *str)
{
int ret;
- ret = match_string(usb_dr_modes, ARRAY_SIZE(usb_dr_modes), str);
+ ret = __match_string(usb_dr_modes, ARRAY_SIZE(usb_dr_modes), str);
return (ret < 0) ? USB_DR_MODE_UNKNOWN : ret;
}
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 2eb623841847..4abc5a76ec51 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -1409,8 +1409,8 @@ EXPORT_SYMBOL_GPL(typec_set_pwr_opmode);
*/
int typec_find_port_power_role(const char *name)
{
- return match_string(typec_port_power_roles,
- ARRAY_SIZE(typec_port_power_roles), name);
+ return __match_string(typec_port_power_roles,
+ ARRAY_SIZE(typec_port_power_roles), name);
}
EXPORT_SYMBOL_GPL(typec_find_port_power_role);
@@ -1424,7 +1424,7 @@ EXPORT_SYMBOL_GPL(typec_find_port_power_role);
*/
int typec_find_power_role(const char *name)
{
- return match_string(typec_roles, ARRAY_SIZE(typec_roles), name);
+ return __match_string(typec_roles, ARRAY_SIZE(typec_roles), name);
}
EXPORT_SYMBOL_GPL(typec_find_power_role);
@@ -1438,8 +1438,8 @@ EXPORT_SYMBOL_GPL(typec_find_power_role);
*/
int typec_find_port_data_role(const char *name)
{
- return match_string(typec_port_data_roles,
- ARRAY_SIZE(typec_port_data_roles), name);
+ return __match_string(typec_port_data_roles,
+ ARRAY_SIZE(typec_port_data_roles), name);
}
EXPORT_SYMBOL_GPL(typec_find_port_data_role);
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index c674abe3cf99..0389e4391faf 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -423,7 +423,7 @@ static int tps6598x_check_mode(struct tps6598x *tps)
if (ret)
return ret;
- switch (match_string(modes, ARRAY_SIZE(modes), mode)) {
+ switch (__match_string(modes, ARRAY_SIZE(modes), mode)) {
case TPS_MODE_APP:
return 0;
case TPS_MODE_BOOT:
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 82fcf07fa9ea..01c7bb7316fb 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -638,9 +638,9 @@ static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
return true;
}
- return match_string(vfio_driver_whitelist,
- ARRAY_SIZE(vfio_driver_whitelist),
- drv->name) >= 0;
+ return __match_string(vfio_driver_whitelist,
+ ARRAY_SIZE(vfio_driver_whitelist),
+ drv->name) >= 0;
}
/*
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
index d59c8a59f582..0025781e6e1e 100644
--- a/drivers/video/fbdev/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
@@ -2129,7 +2129,7 @@ static int of_get_pxafb_display(struct device *dev, struct device_node *disp,
if (ret)
s = "color-tft";
- i = match_string(lcd_types, -1, s);
+ i = __match_string(lcd_types, -1, s);
if (i < 0) {
dev_err(dev, "lcd-type %s is unknown\n", s);
return i;
diff --git a/fs/ubifs/auth.c b/fs/ubifs/auth.c
index 60f43b93d06e..076feb5a9cb6 100644
--- a/fs/ubifs/auth.c
+++ b/fs/ubifs/auth.c
@@ -216,8 +216,8 @@ int ubifs_init_authentication(struct ubifs_info *c)
return -EINVAL;
}
- c->auth_hash_algo = match_string(hash_algo_name, HASH_ALGO__LAST,
- c->auth_hash_name);
+ c->auth_hash_algo = __match_string(hash_algo_name, HASH_ALGO__LAST,
+ c->auth_hash_name);
if ((int)c->auth_hash_algo < 0) {
ubifs_err(c, "Unknown hash algo %s specified",
c->auth_hash_name);
diff --git a/include/linux/string.h b/include/linux/string.h
index 4deb11f7976b..7149fcdf62df 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -195,7 +195,7 @@ static inline int strtobool(const char *s, bool *res)
return kstrtobool(s, res);
}
-int match_string(const char * const *array, size_t n, const char *string);
+int __match_string(const char * const *array, size_t n, const char *string);
int __sysfs_match_string(const char * const *array, size_t n, const char *s);
/**
diff --git a/kernel/cgroup/rdma.c b/kernel/cgroup/rdma.c
index 1d75ae7f1cb7..65d4df148603 100644
--- a/kernel/cgroup/rdma.c
+++ b/kernel/cgroup/rdma.c
@@ -367,7 +367,7 @@ static int parse_resource(char *c, int *intval)
if (!name || !value)
return -EINVAL;
- i = match_string(rdmacg_resource_names, RDMACG_RESOURCE_MAX, name);
+ i = __match_string(rdmacg_resource_names, RDMACG_RESOURCE_MAX, name);
if (i < 0)
return i;
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 678bfb9bd87f..ef89323c1541 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -111,7 +111,7 @@ static int sched_feat_set(char *cmp)
cmp += 3;
}
- i = match_string(sched_feat_names, __SCHED_FEAT_NR, cmp);
+ i = __match_string(sched_feat_names, __SCHED_FEAT_NR, cmp);
if (i < 0)
return i;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 1c80521fd436..a818c6145d94 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4625,7 +4625,7 @@ static int trace_set_options(struct trace_array *tr, char *option)
mutex_lock(&trace_types_lock);
- ret = match_string(trace_options, -1, cmp);
+ ret = __match_string(trace_options, -1, cmp);
/* If no option could be set, test the specific tracer options */
if (ret < 0)
ret = set_tracer_option(tr, cmp, neg);
diff --git a/lib/string.c b/lib/string.c
index e2cf5acc83bd..1797cf31760c 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -666,7 +666,7 @@ bool sysfs_streq(const char *s1, const char *s2)
EXPORT_SYMBOL(sysfs_streq);
/**
- * match_string - matches given string in an array
+ * __match_string - matches given string in an array
* @array: array of strings
* @n: number of strings in the array or -1 for NULL terminated arrays
* @string: string to match with
@@ -674,7 +674,7 @@ EXPORT_SYMBOL(sysfs_streq);
* Return:
* index of a @string in the @array if matches, or %-EINVAL otherwise.
*/
-int match_string(const char * const *array, size_t n, const char *string)
+int __match_string(const char * const *array, size_t n, const char *string)
{
int index;
const char *item;
@@ -692,7 +692,7 @@ int match_string(const char * const *array, size_t n, const char *string)
return -EINVAL;
}
-EXPORT_SYMBOL(match_string);
+EXPORT_SYMBOL(__match_string);
/**
* __sysfs_match_string - matches given string in an array
@@ -700,7 +700,7 @@ EXPORT_SYMBOL(match_string);
* @n: number of strings in the array or -1 for NULL terminated arrays
* @str: string to match with
*
- * Returns index of @str in the @array or -EINVAL, just like match_string().
+ * Returns index of @str in the @array or -EINVAL, just like __match_string().
* Uses sysfs_streq instead of strcmp for matching.
*/
int __sysfs_match_string(const char * const *array, size_t n, const char *str)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 2219e747df49..97bcf4658317 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2755,7 +2755,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
if (flags)
*flags++ = '\0'; /* terminate mode string */
- mode = match_string(policy_modes, MPOL_MAX, str);
+ mode = __match_string(policy_modes, MPOL_MAX, str);
if (mode < 0)
goto out;
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index 4854584ec436..d43f33139568 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -378,7 +378,7 @@ int vmpressure_register_event(struct mem_cgroup *memcg,
/* Find required level */
token = strsep(&spec, ",");
- level = match_string(vmpressure_str_levels, VMPRESSURE_NUM_LEVELS, token);
+ level = __match_string(vmpressure_str_levels, VMPRESSURE_NUM_LEVELS, token);
if (level < 0) {
ret = level;
goto out;
@@ -387,7 +387,7 @@ int vmpressure_register_event(struct mem_cgroup *memcg,
/* Find optional mode */
token = strsep(&spec, ",");
if (token) {
- mode = match_string(vmpressure_str_modes, VMPRESSURE_NUM_MODES, token);
+ mode = __match_string(vmpressure_str_modes, VMPRESSURE_NUM_MODES, token);
if (mode < 0) {
ret = mode;
goto out;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 87500bde5a92..45d28db85e5a 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1480,7 +1480,7 @@ static int param_set_audit(const char *val, const struct kernel_param *kp)
if (apparmor_initialized && !policy_admin_capable(NULL))
return -EPERM;
- i = match_string(audit_mode_names, AUDIT_MAX_INDEX, val);
+ i = __match_string(audit_mode_names, AUDIT_MAX_INDEX, val);
if (i < 0)
return -EINVAL;
@@ -1509,7 +1509,7 @@ static int param_set_mode(const char *val, const struct kernel_param *kp)
if (apparmor_initialized && !policy_admin_capable(NULL))
return -EPERM;
- i = match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX,
+ i = __match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX,
val);
if (i < 0)
return -EINVAL;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 357edd140c09..618842f85f2d 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -61,7 +61,7 @@ static int __init hash_setup(char *str)
goto out;
}
- i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
+ i = __match_string(hash_algo_name, HASH_ALGO__LAST, str);
if (i < 0)
return 1;
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index 3d27f3378d5d..9ec5316f3bb5 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -57,7 +57,7 @@ static bool detect_loud_models(struct fw_unit *unit)
if (err < 0)
return false;
- return match_string(models, ARRAY_SIZE(models), model) >= 0;
+ return __match_string(models, ARRAY_SIZE(models), model) >= 0;
}
static int name_card(struct snd_oxfw *oxfw)
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 81af21ac1439..13c2fb75fd71 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -1086,7 +1086,7 @@ static int add_controls(struct oxygen *chip,
err = snd_ctl_add(chip->card, ctl);
if (err < 0)
return err;
- j = match_string(known_ctl_names, CONTROL_COUNT, ctl->id.name);
+ j = __match_string(known_ctl_names, CONTROL_COUNT, ctl->id.name);
if (j >= 0) {
chip->controls[j] = ctl;
ctl->private_free = oxygen_any_ctl_free;
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index ca172a4b6849..3ef743075bda 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1405,7 +1405,7 @@ static int max98088_get_channel(struct snd_soc_component *component, const char
{
int ret;
- ret = match_string(eq_mode_name, ARRAY_SIZE(eq_mode_name), name);
+ ret = __match_string(eq_mode_name, ARRAY_SIZE(eq_mode_name), name);
if (ret < 0)
dev_err(component->dev, "Bad EQ channel name '%s'\n", name);
return ret;
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 3b3a10da7f40..cd69916d5dcb 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -1636,7 +1636,7 @@ static int max98095_get_bq_channel(struct snd_soc_component *component,
{
int ret;
- ret = match_string(bq_mode_name, ARRAY_SIZE(bq_mode_name), name);
+ ret = __match_string(bq_mode_name, ARRAY_SIZE(bq_mode_name), name);
if (ret < 0)
dev_err(component->dev, "Bad biquad channel name '%s'\n", name);
return ret;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 81a7a12196ff..33ccea0518b1 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -753,7 +753,7 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
item = 0;
}
- i = match_string(e->texts, e->items, control_name);
+ i = __match_string(e->texts, e->items, control_name);
if (i < 0)
return -ENODEV;
--
2.20.1
^ permalink raw reply related
* [PATCH 3/3][V2] lib: re-introduce new match_string() helper/macro
From: Alexandru Ardelean @ 2019-05-28 7:39 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel, linux-ide, linux-clk,
linux-rpi-kernel, linux-arm-kernel, linux-rockchip, linux-pm,
linux-gpio, dri-devel, intel-gfx, linux-omap, linux-mmc,
linux-wireless, netdev, linux-pci, linux-tegra, devel, linux-usb,
kvm, linux-fbdev, linux-mtd, cgroups, linux-mm,
linux-security-module, linux-integrity, alsa-devel
Cc: gregkh, Alexandru Ardelean, heikki.krogerus, andriy.shevchenko
In-Reply-To: <20190528073932.25365-1-alexandru.ardelean@analog.com>
This change re-introduces `match_string()` as a macro that uses
ARRAY_SIZE() to compute the size of the array.
After this change, work can start on migrating subsystems to use this new
helper. Since the original helper is pretty used, migrating to this new one
will take a while, and will be reviewed by each subsystem.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
---
include/linux/string.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/linux/string.h b/include/linux/string.h
index 7149fcdf62df..34491b075449 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -198,6 +198,15 @@ static inline int strtobool(const char *s, bool *res)
int __match_string(const char * const *array, size_t n, const char *string);
int __sysfs_match_string(const char * const *array, size_t n, const char *s);
+/**
+ * match_string - matches given string in an array
+ * @_a: array of strings
+ * @_s: string to match with
+ *
+ * Helper for __match_string(). Calculates the size of @a automatically.
+ */
+#define match_string(_a, _s) __match_string(_a, ARRAY_SIZE(_a), _s)
+
/**
* sysfs_match_string - matches given string in an array
* @_a: array of strings
--
2.20.1
^ permalink raw reply related
* Re: ppc85xx_basic_defconfig is buggy ?
From: Michael Ellerman @ 2019-05-28 8:13 UTC (permalink / raw)
To: Christophe Leroy, linuxppc-dev@lists.ozlabs.org, Paul Mackerras
In-Reply-To: <921cadc8-0f6c-a0f2-b16e-d8129f577c16@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
> ppc85xx_basic_defconfig doesn't not select CONFIG_PPC_85xx.
You mean arch/powerpc/configs/mpc85xx_basic_defconfig presumably.
> Is that expected ?
Yeah it is expected.
It's not intended to be a full defconfig, it's used as a fragment and
merged with other configs, see arch/powerpc/Makefile:
PHONY += mpc85xx_defconfig
mpc85xx_defconfig:
$(call merge_into_defconfig,mpc85xx_basic_defconfig,\
85xx-32bit 85xx-hw fsl-emb-nonhw)
Where 85xx-32bit.config is:
CONFIG_HIGHMEM=y
CONFIG_KEXEC=y
CONFIG_PPC_85xx=y
CONFIG_PROC_KCORE=y
CONFIG_PHYS_64BIT=y
So that's where PPC_85xx gets set.
But it's confusing that mpc85xx_basic_defconfig is named "foo_defconfig"
but is not actually a proper defconfig. We should rename it to
mpc85xx_basic.config to make it clearer that it's a fragment. I'll do a
patch.
cheers
^ permalink raw reply
* [PATCH] powerpc/configs: Rename foo_basic_defconfig to foo_base.config
From: Michael Ellerman @ 2019-05-28 8:16 UTC (permalink / raw)
To: linuxppc-dev
We have several "defconfigs" that are not actually full defconfigs
they are just a base set of options which are then merged with other
fragments to produce a working defconfig.
The most obvious example is corenet_basic_defconfig which only
contains one symbol CONFIG_CORENET_GENERIC=y. But there is also
mpc85xx_base_defconfig which doesn't actually enable CONFIG_PPC_85xx.
To avoid confusion, rename these config fragments to "foo_base.config"
to make it clearer that they are not full defconfigs.
Reported-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/Makefile | 12 ++++++------
.../{corenet_basic_defconfig => corenet_base.config} | 0
.../{mpc85xx_basic_defconfig => mpc85xx_base.config} | 0
.../{mpc86xx_basic_defconfig => mpc86xx_base.config} | 0
4 files changed, 6 insertions(+), 6 deletions(-)
rename arch/powerpc/configs/{corenet_basic_defconfig => corenet_base.config} (100%)
rename arch/powerpc/configs/{mpc85xx_basic_defconfig => mpc85xx_base.config} (100%)
rename arch/powerpc/configs/{mpc86xx_basic_defconfig => mpc86xx_base.config} (100%)
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index c345b79414a9..94f735db2229 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -333,32 +333,32 @@ PHONY += powernv_be_defconfig
PHONY += mpc85xx_defconfig
mpc85xx_defconfig:
- $(call merge_into_defconfig,mpc85xx_basic_defconfig,\
+ $(call merge_into_defconfig,mpc85xx_base.config,\
85xx-32bit 85xx-hw fsl-emb-nonhw)
PHONY += mpc85xx_smp_defconfig
mpc85xx_smp_defconfig:
- $(call merge_into_defconfig,mpc85xx_basic_defconfig,\
+ $(call merge_into_defconfig,mpc85xx_base.config,\
85xx-32bit 85xx-smp 85xx-hw fsl-emb-nonhw)
PHONY += corenet32_smp_defconfig
corenet32_smp_defconfig:
- $(call merge_into_defconfig,corenet_basic_defconfig,\
+ $(call merge_into_defconfig,corenet_base.config,\
85xx-32bit 85xx-smp 85xx-hw fsl-emb-nonhw dpaa)
PHONY += corenet64_smp_defconfig
corenet64_smp_defconfig:
- $(call merge_into_defconfig,corenet_basic_defconfig,\
+ $(call merge_into_defconfig,corenet_base.config,\
85xx-64bit 85xx-smp altivec 85xx-hw fsl-emb-nonhw dpaa)
PHONY += mpc86xx_defconfig
mpc86xx_defconfig:
- $(call merge_into_defconfig,mpc86xx_basic_defconfig,\
+ $(call merge_into_defconfig,mpc86xx_base.config,\
86xx-hw fsl-emb-nonhw)
PHONY += mpc86xx_smp_defconfig
mpc86xx_smp_defconfig:
- $(call merge_into_defconfig,mpc86xx_basic_defconfig,\
+ $(call merge_into_defconfig,mpc86xx_base.config,\
86xx-smp 86xx-hw fsl-emb-nonhw)
PHONY += ppc32_allmodconfig
diff --git a/arch/powerpc/configs/corenet_basic_defconfig b/arch/powerpc/configs/corenet_base.config
similarity index 100%
rename from arch/powerpc/configs/corenet_basic_defconfig
rename to arch/powerpc/configs/corenet_base.config
diff --git a/arch/powerpc/configs/mpc85xx_basic_defconfig b/arch/powerpc/configs/mpc85xx_base.config
similarity index 100%
rename from arch/powerpc/configs/mpc85xx_basic_defconfig
rename to arch/powerpc/configs/mpc85xx_base.config
diff --git a/arch/powerpc/configs/mpc86xx_basic_defconfig b/arch/powerpc/configs/mpc86xx_base.config
similarity index 100%
rename from arch/powerpc/configs/mpc86xx_basic_defconfig
rename to arch/powerpc/configs/mpc86xx_base.config
--
2.20.1
^ permalink raw reply related
* Re: [PATCH v1 08/15] crypto: talitos - Do not modify req->cryptlen on decryption.
From: Horia Geanta @ 2019-05-28 8:20 UTC (permalink / raw)
To: Christophe Leroy, Herbert Xu, David S. Miller
Cc: linuxppc-dev@lists.ozlabs.org, linux-crypto@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <1ad8020c8140da1b4f818220e130ed0074c37fe1.1558445259.git.christophe.leroy@c-s.fr>
On 5/21/2019 4:34 PM, Christophe Leroy wrote:
> For decrypt, req->cryptlen includes the size of the authentication
> part while all functions of the driver expect cryptlen to be
> the size of the encrypted data.
>
> As it is not expected to change req->cryptlen, this patch
> implements local calculation of cryptlen.
>
An alternative would be to restore req->cryptlen in the *_done() callback.
It would be easier to implement, though probably less intuitive.
Horia
^ permalink raw reply
* [PATCH v2] mm: Move MAP_SYNC to asm-generic/mman-common.h
From: Aneesh Kumar K.V @ 2019-05-28 9:11 UTC (permalink / raw)
To: akpm, jack, mpe; +Cc: linux-mm, linuxppc-dev, linux-kernel, Aneesh Kumar K.V
This enables support for synchronous DAX fault on powerpc
The generic changes are added as part of
commit b6fb293f2497 ("mm: Define MAP_SYNC and VM_SYNC flags")
Without this, mmap returns EOPNOTSUPP for MAP_SYNC with MAP_SHARED_VALIDATE
Instead of adding MAP_SYNC with same value to
arch/powerpc/include/uapi/asm/mman.h, I am moving the #define to
asm-generic/mman-common.h. Two architectures using mman-common.h directly are
sparc and powerpc. We should be able to consloidate more #defines to
mman-common.h. That can be done as a separate patch.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
Changes from V1:
* Move #define to mman-common.h instead of powerpc specific mman.h change
include/uapi/asm-generic/mman-common.h | 3 ++-
include/uapi/asm-generic/mman.h | 1 -
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
index abd238d0f7a4..bea0278f65ab 100644
--- a/include/uapi/asm-generic/mman-common.h
+++ b/include/uapi/asm-generic/mman-common.h
@@ -25,7 +25,8 @@
# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
#endif
-/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
+/* 0x0100 - 0x40000 flags are defined in asm-generic/mman.h */
+#define MAP_SYNC 0x080000 /* perform synchronous page faults for the mapping */
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
/*
diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h
index 653687d9771b..2dffcbf705b3 100644
--- a/include/uapi/asm-generic/mman.h
+++ b/include/uapi/asm-generic/mman.h
@@ -13,7 +13,6 @@
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
-#define MAP_SYNC 0x80000 /* perform synchronous page faults for the mapping */
/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
--
2.21.0
^ permalink raw reply related
* Re: [PATCH v1 00/15] Fixing selftests failure on Talitos driver
From: Horia Geanta @ 2019-05-28 9:17 UTC (permalink / raw)
To: Christophe Leroy, Herbert Xu, David S. Miller
Cc: linuxppc-dev@lists.ozlabs.org, linux-crypto@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <cover.1558445259.git.christophe.leroy@c-s.fr>
On 5/21/2019 4:34 PM, Christophe Leroy wrote:
> Several test failures have popped up following recent changes to crypto
> selftests.
>
> This series fixes (most of) them.
>
> The last three patches are trivial cleanups.
>
Thanks Christophe.
For the series:
Reviewed-by: Horia Geantă <horia.geanta@nxp.com>
Have you validated the changes also on SEC 2.x+?
Asking since IIRC you mentioned having only HW with SEC 1 and changes in patch
"crypto: talitos - fix AEAD processing." look quite complex.
Thanks,
Horia
^ permalink raw reply
* Re: [PATCH v2] mm: Move MAP_SYNC to asm-generic/mman-common.h
From: Jan Kara @ 2019-05-28 9:27 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: jack, linux-kernel, linux-mm, akpm, linuxppc-dev
In-Reply-To: <20190528091120.13322-1-aneesh.kumar@linux.ibm.com>
On Tue 28-05-19 14:41:20, Aneesh Kumar K.V wrote:
> This enables support for synchronous DAX fault on powerpc
>
> The generic changes are added as part of
> commit b6fb293f2497 ("mm: Define MAP_SYNC and VM_SYNC flags")
>
> Without this, mmap returns EOPNOTSUPP for MAP_SYNC with MAP_SHARED_VALIDATE
>
> Instead of adding MAP_SYNC with same value to
> arch/powerpc/include/uapi/asm/mman.h, I am moving the #define to
> asm-generic/mman-common.h. Two architectures using mman-common.h directly are
> sparc and powerpc. We should be able to consloidate more #defines to
> mman-common.h. That can be done as a separate patch.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Looks good to me FWIW (I don't have much experience with mmap flags and
their peculirarities). So feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> Changes from V1:
> * Move #define to mman-common.h instead of powerpc specific mman.h change
>
>
> include/uapi/asm-generic/mman-common.h | 3 ++-
> include/uapi/asm-generic/mman.h | 1 -
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/uapi/asm-generic/mman-common.h b/include/uapi/asm-generic/mman-common.h
> index abd238d0f7a4..bea0278f65ab 100644
> --- a/include/uapi/asm-generic/mman-common.h
> +++ b/include/uapi/asm-generic/mman-common.h
> @@ -25,7 +25,8 @@
> # define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
> #endif
>
> -/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
> +/* 0x0100 - 0x40000 flags are defined in asm-generic/mman.h */
> +#define MAP_SYNC 0x080000 /* perform synchronous page faults for the mapping */
> #define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
>
> /*
> diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h
> index 653687d9771b..2dffcbf705b3 100644
> --- a/include/uapi/asm-generic/mman.h
> +++ b/include/uapi/asm-generic/mman.h
> @@ -13,7 +13,6 @@
> #define MAP_NONBLOCK 0x10000 /* do not block on IO */
> #define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
> #define MAP_HUGETLB 0x40000 /* create a huge page mapping */
> -#define MAP_SYNC 0x80000 /* perform synchronous page faults for the mapping */
>
> /* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
>
> --
> 2.21.0
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v2] mm: hwpoison: disable memory error handling on 1GB hugepage
From: Wanpeng Li @ 2019-05-28 9:49 UTC (permalink / raw)
To: Mike Kravetz
Cc: kvm, Punit Agrawal, Xiao Guangrong, linux-kernel@vger.kernel.org,
Michal Hocko, linux-mm@kvack.org, yongkaiwu, Aneesh Kumar K.V,
Paolo Bonzini, Andrew Morton, lidongchen,
linuxppc-dev@lists.ozlabs.org, Naoya Horiguchi, Anshuman Khandual
In-Reply-To: <e673f38a-9e5f-21f6-421b-b3cb4ff02e91@oracle.com>
Cc Paolo,
Hi all,
On Wed, 14 Feb 2018 at 06:34, Mike Kravetz <mike.kravetz@oracle.com> wrote:
>
> On 02/12/2018 06:48 PM, Michael Ellerman wrote:
> > Andrew Morton <akpm@linux-foundation.org> writes:
> >
> >> On Thu, 08 Feb 2018 12:30:45 +0000 Punit Agrawal <punit.agrawal@arm.com> wrote:
> >>
> >>>>
> >>>> So I don't think that the above test result means that errors are properly
> >>>> handled, and the proposed patch should help for arm64.
> >>>
> >>> Although, the deviation of pud_huge() avoids a kernel crash the code
> >>> would be easier to maintain and reason about if arm64 helpers are
> >>> consistent with expectations by core code.
> >>>
> >>> I'll look to update the arm64 helpers once this patch gets merged. But
> >>> it would be helpful if there was a clear expression of semantics for
> >>> pud_huge() for various cases. Is there any version that can be used as
> >>> reference?
> >>
> >> Is that an ack or tested-by?
> >>
> >> Mike keeps plaintively asking the powerpc developers to take a look,
> >> but they remain steadfastly in hiding.
> >
> > Cc'ing linuxppc-dev is always a good idea :)
> >
>
> Thanks Michael,
>
> I was mostly concerned about use cases for soft/hard offline of huge pages
> larger than PMD_SIZE on powerpc. I know that powerpc supports PGD_SIZE
> huge pages, and soft/hard offline support was specifically added for this.
> See, 94310cbcaa3c "mm/madvise: enable (soft|hard) offline of HugeTLB pages
> at PGD level"
>
> This patch will disable that functionality. So, at a minimum this is a
> 'heads up'. If there are actual use cases that depend on this, then more
> work/discussions will need to happen. From the e-mail thread on PGD_SIZE
> support, I can not tell if there is a real use case or this is just a
> 'nice to have'.
1GB hugetlbfs pages are used by DPDK and VMs in cloud deployment, we
encounter gup_pud_range() panic several times in product environment.
Is there any plan to reenable and fix arch codes?
In addition, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kvm/mmu.c#n3213
The memory in guest can be 1GB/2MB/4K, though the host-backed memory
are 1GB hugetlbfs pages, after above PUD panic is fixed,
try_to_unmap() which is called in MCA recovery path will mark the PUD
hwpoison entry. The guest will vmexit and retry endlessly when
accessing any memory in the guest which is backed by this 1GB poisoned
hugetlbfs page. We have a plan to split this 1GB hugetblfs page by 2MB
hugetlbfs pages/4KB pages, maybe file remap to a virtual address range
which is 2MB/4KB page granularity, also split the KVM MMU 1GB SPTE
into 2MB/4KB and mark the offensive SPTE w/ a hwpoison flag, a sigbus
will be delivered to VM at page fault next time for the offensive
SPTE. Is this proposal acceptable?
Regards,
Wanpeng Li
^ permalink raw reply
* Re: [PATCH 1/2] perf ioctl: Add check for the sample_period value
From: Michael Ellerman @ 2019-05-28 9:50 UTC (permalink / raw)
To: Ravi Bangoria, Peter Zijlstra
Cc: Ravi Bangoria, maddy, jolsa, linux-kernel, acme, linuxppc-dev
In-Reply-To: <d2d34084-999d-9be2-511e-82625b80aa40@linux.ibm.com>
Ravi Bangoria <ravi.bangoria@linux.ibm.com> writes:
> On 5/13/19 2:26 PM, Peter Zijlstra wrote:
>> On Mon, May 13, 2019 at 09:42:13AM +0200, Peter Zijlstra wrote:
>>> On Sat, May 11, 2019 at 08:12:16AM +0530, Ravi Bangoria wrote:
>>>> Add a check for sample_period value sent from userspace. Negative
>>>> value does not make sense. And in powerpc arch code this could cause
>>>> a recursive PMI leading to a hang (reported when running perf-fuzzer).
>>>>
>>>> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
>>>> ---
>>>> kernel/events/core.c | 3 +++
>>>> 1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/kernel/events/core.c b/kernel/events/core.c
>>>> index abbd4b3b96c2..e44c90378940 100644
>>>> --- a/kernel/events/core.c
>>>> +++ b/kernel/events/core.c
>>>> @@ -5005,6 +5005,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
>>>> if (perf_event_check_period(event, value))
>>>> return -EINVAL;
>>>>
>>>> + if (!event->attr.freq && (value & (1ULL << 63)))
>>>> + return -EINVAL;
>>>
>>> Well, perf_event_attr::sample_period is __u64. Would not be the site
>>> using it as signed be the one in error?
>>
>> You forgot to mention commit: 0819b2e30ccb9, so I guess this just makes
>> it consistent and is fine.
>>
>
> Yeah, I was about to reply :)
I've taken patch 2. You should probably do a v2 of patch 1 with an
updated change log that explains things fully?
cheers
^ permalink raw reply
* Re: [PATCH v2 2/2] tests: add close_range() tests
From: Christian Brauner @ 2019-05-28 9:57 UTC (permalink / raw)
To: Michael Ellerman
Cc: linux-ia64, linux-sh, oleg, dhowells, linux-kselftest, sparclinux,
shuah, linux-arch, linux-s390, miklos, x86, torvalds, linux-mips,
linux-xtensa, tkjos, arnd, jannh, linux-m68k, viro, tglx, ldv,
linux-arm-kernel, fweimer, linux-parisc, linux-api, linux-kernel,
linux-alpha, linux-fsdevel, linuxppc-dev
In-Reply-To: <8736kzqpdm.fsf@concordia.ellerman.id.au>
On Tue, May 28, 2019 at 12:33:41PM +1000, Michael Ellerman wrote:
> Christian Brauner <christian@brauner.io> writes:
> > This adds basic tests for the new close_range() syscall.
> > - test that no invalid flags can be passed
> > - test that a range of file descriptors is correctly closed
> > - test that a range of file descriptors is correctly closed if there there
> > are already closed file descriptors in the range
> > - test that max_fd is correctly capped to the current fdtable maximum
> >
> > Signed-off-by: Christian Brauner <christian@brauner.io>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Jann Horn <jannh@google.com>
> > Cc: David Howells <dhowells@redhat.com>
> > Cc: Dmitry V. Levin <ldv@altlinux.org>
> > Cc: Oleg Nesterov <oleg@redhat.com>
> > Cc: Linus Torvalds <torvalds@linux-foundation.org>
> > Cc: Florian Weimer <fweimer@redhat.com>
> > Cc: linux-api@vger.kernel.org
> > ---
> > v1: unchanged
> > v2:
> > - Christian Brauner <christian@brauner.io>:
> > - verify that close_range() correctly closes a single file descriptor
> > ---
> > tools/testing/selftests/Makefile | 1 +
> > tools/testing/selftests/core/.gitignore | 1 +
> > tools/testing/selftests/core/Makefile | 6 +
> > .../testing/selftests/core/close_range_test.c | 142 ++++++++++++++++++
> > 4 files changed, 150 insertions(+)
> > create mode 100644 tools/testing/selftests/core/.gitignore
> > create mode 100644 tools/testing/selftests/core/Makefile
> > create mode 100644 tools/testing/selftests/core/close_range_test.c
> >
> > diff --git a/tools/testing/selftests/core/.gitignore b/tools/testing/selftests/core/.gitignore
> > new file mode 100644
> > index 000000000000..6e6712ce5817
> > --- /dev/null
> > +++ b/tools/testing/selftests/core/.gitignore
> > @@ -0,0 +1 @@
> > +close_range_test
> > diff --git a/tools/testing/selftests/core/Makefile b/tools/testing/selftests/core/Makefile
> > new file mode 100644
> > index 000000000000..de3ae68aa345
> > --- /dev/null
> > +++ b/tools/testing/selftests/core/Makefile
> > @@ -0,0 +1,6 @@
> > +CFLAGS += -g -I../../../../usr/include/ -I../../../../include
>
> Your second -I pulls the unexported kernel headers in, userspace
> programs shouldn't include unexported kernel headers.
>
> It breaks the build on powerpc with eg:
>
> powerpc64le-linux-gnu-gcc -g -I../../../../usr/include/ -I../../../../include close_range_test.c -o /output/kselftest/core/close_range_test
> In file included from /usr/powerpc64le-linux-gnu/include/bits/fcntl-linux.h:346,
> from /usr/powerpc64le-linux-gnu/include/bits/fcntl.h:62,
> from /usr/powerpc64le-linux-gnu/include/fcntl.h:35,
> from close_range_test.c:5:
> ../../../../include/linux/falloc.h:13:2: error: unknown type name '__s16'
> __s16 l_type;
> ^~~~~
>
>
> Did you do that on purpose or just copy it from one of the other
> Makefiles? :)
I originally did that on purpose because checkpatch was yammering on
about me not having used ARRAY_SIZE(). But that include can go, you are
right.
Christian
^ permalink raw reply
* Re: [PATCH] [RFC] Remove bdflush syscall stub
From: Andreas Schwab @ 2019-05-28 10:25 UTC (permalink / raw)
To: Cyril Hrubis
Cc: linux-s390, Michal Simek, linux-ia64, linux-parisc, linux-sh,
linux-api, linux-xtensa, lkml, linux-mips, linux-fsdevel,
linux-m68k, linux-alpha, sparclinux, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <20190528101012.11402-1-chrubis@suse.cz>
On Mai 28 2019, Cyril Hrubis <chrubis@suse.cz> wrote:
> I've tested the patch on i386. Before the patch calling bdflush() with
> attempt to tune a variable returned 0 and after the patch the syscall
> fails with EINVAL.
Should be ENOSYS, doesn't it?
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply
* Re: [PATCH] [RFC] Remove bdflush syscall stub
From: Florian Weimer @ 2019-05-28 11:03 UTC (permalink / raw)
To: Cyril Hrubis
Cc: linux-s390, Michal Simek, linux-ia64, linux-parisc, linux-sh,
linux-api, linux-xtensa, lkml, linux-mips, linux-fsdevel,
linux-m68k, Andreas Schwab, linux-alpha, sparclinux, linuxppc-dev,
linux-arm-kernel
In-Reply-To: <20190528104017.GA11969@rei>
* Cyril Hrubis:
> Hi!
>> > I've tested the patch on i386. Before the patch calling bdflush() with
>> > attempt to tune a variable returned 0 and after the patch the syscall
>> > fails with EINVAL.
>>
>> Should be ENOSYS, doesn't it?
>
> My bad, the LTP syscall wrapper handles ENOSYS and produces skipped
> results based on that.
>
> EINVAL is what you get for not yet implemented syscalls, i.e. new
> syscall on old kernel.
EINVAL? Is that a bdflush-specific thing, test-specific, or is itmore
general?
glibc has fallback paths that test for ENOSYS only. EINVAL will be
passed to the application, skipping fallback. For missing system calls,
this is not what we want.
Thanks,
Florian
^ permalink raw reply
* Re: [PATCH v2] powerpc/32: sstep: Move variable `rc` within CONFIG_PPC64 sentinels
From: Michael Ellerman @ 2019-05-28 11:40 UTC (permalink / raw)
To: Mathieu Malaterre
Cc: Mathieu Malaterre, linux-kernel, Paul Mackerras, linuxppc-dev
In-Reply-To: <20190312212318.17822-1-malat@debian.org>
Mathieu Malaterre <malat@debian.org> writes:
> Fix warnings treated as errors with W=1:
>
> arch/powerpc/lib/sstep.c:1172:31: error: variable 'rc' set but not used [-Werror=unused-but-set-variable]
>
> Suggested-by: Christophe Leroy <christophe.leroy@c-s.fr>
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> ---
> v2: as suggested prefer CONFIG_PPC64 sentinel instead of unused keyword
I'd rather avoid adding more ifdefs if we can.
I think this works?
cheers
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 3d33fb509ef4..600b036ddfda 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1169,7 +1169,7 @@ static nokprobe_inline int trap_compare(long v1, long v2)
int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
unsigned int instr)
{
- unsigned int opcode, ra, rb, rc, rd, spr, u;
+ unsigned int opcode, ra, rb, rd, spr, u;
unsigned long int imm;
unsigned long int val, val2;
unsigned int mb, me, sh;
@@ -1292,7 +1292,6 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
rd = (instr >> 21) & 0x1f;
ra = (instr >> 16) & 0x1f;
rb = (instr >> 11) & 0x1f;
- rc = (instr >> 6) & 0x1f;
switch (opcode) {
#ifdef __powerpc64__
@@ -1307,10 +1306,14 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
return 1;
#ifdef __powerpc64__
- case 4:
+ case 4: {
+ unsigned int rc;
+
if (!cpu_has_feature(CPU_FTR_ARCH_300))
return -1;
+ rc = (instr >> 6) & 0x1f;
+
switch (instr & 0x3f) {
case 48: /* maddhd */
asm volatile(PPC_MADDHD(%0, %1, %2, %3) :
@@ -1336,6 +1339,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
* primary opcode which do not have emulation support yet.
*/
return -1;
+ }
#endif
case 7: /* mulli */
^ permalink raw reply related
* Re: [PATCH v4 3/3] kselftest: Extend vDSO selftest to clock_getres
From: Vincenzo Frascino @ 2019-05-28 11:57 UTC (permalink / raw)
To: Michael Ellerman, linux-arch, linuxppc-dev, linux-s390,
linux-kselftest
Cc: Arnd Bergmann, Heiko Carstens, Paul Mackerras, Martin Schwidefsky,
Thomas Gleixner, Shuah Khan
In-Reply-To: <87lfyrp0d2.fsf@concordia.ellerman.id.au>
Hi Michael,
thank you for your reply.
On 28/05/2019 07:19, Michael Ellerman wrote:
> Vincenzo Frascino <vincenzo.frascino@arm.com> writes:
>
>> The current version of the multiarch vDSO selftest verifies only
>> gettimeofday.
>>
>> Extend the vDSO selftest to clock_getres, to verify that the
>> syscall and the vDSO library function return the same information.
>>
>> The extension has been used to verify the hrtimer_resoltion fix.
>
> This is passing for me even without patch 1 applied, shouldn't it fail
> without the fix? What am I missing?
>
This is correct, because during the refactoring process I missed an "n" :)
if·((x.tv_sec·!=·y.tv_sec)·||·(x.tv_sec·!=·y.tv_sec))
Should be:
if·((x.tv_sec·!=·y.tv_sec)·||·(x.tv_nsec·!=·y.tv_nsec))
My mistake, I am going to fix the test and re-post v5 of this set.
Without my patch if you pass "highres=off" to the kernel (as a command line
parameter) it leads to a broken implementation of clock_getres since the value
of CLOCK_REALTIME_RES does not change at runtime.
Expected result (with highres=off):
# uname -r
5.2.0-rc2
# ./vdso_clock_getres
clock_id: CLOCK_REALTIME [FAIL]
clock_id: CLOCK_BOOTTIME [PASS]
clock_id: CLOCK_TAI [PASS]
clock_id: CLOCK_REALTIME_COARSE [PASS]
clock_id: CLOCK_MONOTONIC [FAIL]
clock_id: CLOCK_MONOTONIC_RAW [PASS]
clock_id: CLOCK_MONOTONIC_COARSE [PASS]
The reason of this behavior is that the only clocks supported by getres on
powerpc are CLOCK_REALTIME and CLOCK_MONOTONIC, the rest on the clocks use
always syscalls.
> # uname -r
> 5.2.0-rc2-gcc-8.2.0
>
> # ./vdso_clock_getres
> clock_id: CLOCK_REALTIME [PASS]
> clock_id: CLOCK_BOOTTIME [PASS]
> clock_id: CLOCK_TAI [PASS]
> clock_id: CLOCK_REALTIME_COARSE [PASS]
> clock_id: CLOCK_MONOTONIC [PASS]
> clock_id: CLOCK_MONOTONIC_RAW [PASS]
> clock_id: CLOCK_MONOTONIC_COARSE [PASS]
>
> cheers
>
>> Cc: Shuah Khan <shuah@kernel.org>
>> Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
>> ---
>>
>> Note: This patch is independent from the others in this series, hence it
>> can be merged singularly by the kselftest maintainers.
>>
>> tools/testing/selftests/vDSO/Makefile | 2 +
>> .../selftests/vDSO/vdso_clock_getres.c | 124 ++++++++++++++++++
>> 2 files changed, 126 insertions(+)
>> create mode 100644 tools/testing/selftests/vDSO/vdso_clock_getres.c
--
Regards,
Vincenzo
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox