All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 00/14] kvm/arm: Align the VMID allocation with the arm64 ASID one
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: suzuki.poulose, marc.zyngier, catalin.marinas, julien.thierry,
	will.deacon, Russell King, Julien Grall, james.morse

Hi all,

This patch series is moving out the ASID allocator in a separate file in order
to re-use it for the VMID. The benefits are:
    - CPUs are not forced to exit on a roll-over.
    - Context invalidation is now per-CPU rather than
      broadcasted.

There are no performance regression on the fastpath for ASID allocation.
Actually on the hackbench measurement (300 hackbench) it was .7% faster.

The measurement was made on a Seattle based SoC (8 CPUs), with the
number of VMID limited to 4-bit. The test involves running concurrently 40
guests with 2 vCPUs. Each guest will then execute hackbench 5 times
before exiting.

The performance difference (on 5.1-rc1) between the current algo and the
new one are:
    - 2.5% less exit from the guest
    - 22.4% more flush, although they are now local rather than broadcasted
    - 0.11% faster (just for the record)

The ASID allocator rework to make it generic has been divided in multiple
patches to make the review easier.

Compare to the first RFC, Arm is not duplicated most of the code anymore.
Instead, Arm will build the version from Arm64.

A branch with the patch based on 5.2-rc5 can be found:

http://xenbits.xen.org/gitweb/?p=people/julieng/linux-arm.git;a=shortlog;h=refs/heads/vmid-rework/rfc-v2

Best regards,

Cc: Russell King <linux@armlinux.org.uk>

Julien Grall (14):
  arm64/mm: Introduce asid_info structure and move
    asid_generation/asid_map to it
  arm64/mm: Move active_asids and reserved_asids to asid_info
  arm64/mm: Move bits to asid_info
  arm64/mm: Move the variable lock and tlb_flush_pending to asid_info
  arm64/mm: Remove dependency on MM in new_context
  arm64/mm: Store the number of asid allocated per context
  arm64/mm: Introduce NUM_ASIDS
  arm64/mm: Split asid_inits in 2 parts
  arm64/mm: Split the function check_and_switch_context in 3 parts
  arm64/mm: Introduce a callback to flush the local context
  arm64: Move the ASID allocator code in a separate file
  arm64/lib: asid: Allow user to update the context under the lock
  arm/kvm: Introduce a new VMID allocator
  kvm/arm: Align the VMID allocation with the arm64 ASID one

 arch/arm/include/asm/kvm_asm.h    |   2 +-
 arch/arm/include/asm/kvm_host.h   |   5 +-
 arch/arm/include/asm/kvm_hyp.h    |   1 +
 arch/arm/include/asm/lib_asid.h   |  81 +++++++++++++++
 arch/arm/kvm/Makefile             |   1 +
 arch/arm/kvm/hyp/tlb.c            |   8 +-
 arch/arm64/include/asm/kvm_asid.h |   8 ++
 arch/arm64/include/asm/kvm_asm.h  |   2 +-
 arch/arm64/include/asm/kvm_host.h |   5 +-
 arch/arm64/include/asm/lib_asid.h |  81 +++++++++++++++
 arch/arm64/kvm/hyp/tlb.c          |  10 +-
 arch/arm64/lib/Makefile           |   2 +
 arch/arm64/lib/asid.c             | 191 +++++++++++++++++++++++++++++++++++
 arch/arm64/mm/context.c           | 205 ++++++--------------------------------
 virt/kvm/arm/arm.c                | 112 +++++++--------------
 15 files changed, 447 insertions(+), 267 deletions(-)
 create mode 100644 arch/arm/include/asm/lib_asid.h
 create mode 100644 arch/arm64/include/asm/kvm_asid.h
 create mode 100644 arch/arm64/include/asm/lib_asid.h
 create mode 100644 arch/arm64/lib/asid.c

-- 
2.11.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [RFC v2 08/14] arm64/mm: Split asid_inits in 2 parts
From: Julien Grall @ 2019-06-20 13:06 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

Move out the common initialization of the ASID allocator in a separate
function.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 43 +++++++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index beba8e5b4100..81bc3d365436 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -271,31 +271,50 @@ asmlinkage void post_ttbr_update_workaround(void)
 			CONFIG_CAVIUM_ERRATUM_27456));
 }
 
-static int asids_init(void)
+/*
+ * Initialize the ASID allocator
+ *
+ * @info: Pointer to the asid allocator structure
+ * @bits: Number of ASIDs available
+ * @asid_per_ctxt: Number of ASIDs to allocate per-context. ASIDs are
+ * allocated contiguously for a given context. This value should be a power of
+ * 2.
+ */
+static int asid_allocator_init(struct asid_info *info,
+			       u32 bits, unsigned int asid_per_ctxt)
 {
-	struct asid_info *info = &asid_info;
-
-	info->bits = get_cpu_asid_bits();
-	info->ctxt_shift = ilog2(ASID_PER_CONTEXT);
+	info->bits = bits;
+	info->ctxt_shift = ilog2(asid_per_ctxt);
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
-	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
+	 * one more ASID than CPUs. ASID #0 is always reserved.
 	 */
 	WARN_ON(NUM_CTXT_ASIDS(info) - 1 <= num_possible_cpus());
 	atomic64_set(&info->generation, ASID_FIRST_VERSION(info));
 	info->map = kcalloc(BITS_TO_LONGS(NUM_CTXT_ASIDS(info)),
 			    sizeof(*info->map), GFP_KERNEL);
 	if (!info->map)
-		panic("Failed to allocate bitmap for %lu ASIDs\n",
-		      NUM_CTXT_ASIDS(info));
-
-	info->active = &active_asids;
-	info->reserved = &reserved_asids;
+		return -ENOMEM;
 
 	raw_spin_lock_init(&info->lock);
 
+	return 0;
+}
+
+static int asids_init(void)
+{
+	u32 bits = get_cpu_asid_bits();
+
+	if (!asid_allocator_init(&asid_info, bits, ASID_PER_CONTEXT))
+		panic("Unable to initialize ASID allocator for %lu ASIDs\n",
+		      1UL << bits);
+
+	asid_info.active = &active_asids;
+	asid_info.reserved = &reserved_asids;
+
 	pr_info("ASID allocator initialised with %lu entries\n",
-		NUM_CTXT_ASIDS(info));
+		NUM_CTXT_ASIDS(&asid_info));
+
 	return 0;
 }
 early_initcall(asids_init);
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 07/14] arm64/mm: Introduce NUM_ASIDS
From: Julien Grall @ 2019-06-20 13:06 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

At the moment ASID_FIRST_VERSION is used to know the number of ASIDs
supported. As we are going to move the ASID allocator in a separate, it
would be better to use a different name for external users.

This patch adds NUM_ASIDS and implements ASID_FIRST_VERSION using it.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index d128f02644b0..beba8e5b4100 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -48,7 +48,9 @@ static DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 
 #define ASID_MASK(info)			(~GENMASK((info)->bits - 1, 0))
-#define ASID_FIRST_VERSION(info)	(1UL << ((info)->bits))
+#define NUM_ASIDS(info)			(1UL << ((info)->bits))
+
+#define ASID_FIRST_VERSION(info)	NUM_ASIDS(info)
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 #define ASID_PER_CONTEXT		2
@@ -56,7 +58,7 @@ static DEFINE_PER_CPU(u64, reserved_asids);
 #define ASID_PER_CONTEXT		1
 #endif
 
-#define NUM_CTXT_ASIDS(info)		(ASID_FIRST_VERSION(info) >> (info)->ctxt_shift)
+#define NUM_CTXT_ASIDS(info)		(NUM_ASIDS(info) >> (info)->ctxt_shift)
 #define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> (info)->ctxt_shift)
 #define idx2asid(info, idx)		(((idx) << (info)->ctxt_shift) & ~ASID_MASK(info))
 
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 08/14] arm64/mm: Split asid_inits in 2 parts
From: Julien Grall @ 2019-06-20 13:06 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: james.morse, marc.zyngier, julien.thierry, suzuki.poulose,
	catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

Move out the common initialization of the ASID allocator in a separate
function.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 43 +++++++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index beba8e5b4100..81bc3d365436 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -271,31 +271,50 @@ asmlinkage void post_ttbr_update_workaround(void)
 			CONFIG_CAVIUM_ERRATUM_27456));
 }
 
-static int asids_init(void)
+/*
+ * Initialize the ASID allocator
+ *
+ * @info: Pointer to the asid allocator structure
+ * @bits: Number of ASIDs available
+ * @asid_per_ctxt: Number of ASIDs to allocate per-context. ASIDs are
+ * allocated contiguously for a given context. This value should be a power of
+ * 2.
+ */
+static int asid_allocator_init(struct asid_info *info,
+			       u32 bits, unsigned int asid_per_ctxt)
 {
-	struct asid_info *info = &asid_info;
-
-	info->bits = get_cpu_asid_bits();
-	info->ctxt_shift = ilog2(ASID_PER_CONTEXT);
+	info->bits = bits;
+	info->ctxt_shift = ilog2(asid_per_ctxt);
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
-	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
+	 * one more ASID than CPUs. ASID #0 is always reserved.
 	 */
 	WARN_ON(NUM_CTXT_ASIDS(info) - 1 <= num_possible_cpus());
 	atomic64_set(&info->generation, ASID_FIRST_VERSION(info));
 	info->map = kcalloc(BITS_TO_LONGS(NUM_CTXT_ASIDS(info)),
 			    sizeof(*info->map), GFP_KERNEL);
 	if (!info->map)
-		panic("Failed to allocate bitmap for %lu ASIDs\n",
-		      NUM_CTXT_ASIDS(info));
-
-	info->active = &active_asids;
-	info->reserved = &reserved_asids;
+		return -ENOMEM;
 
 	raw_spin_lock_init(&info->lock);
 
+	return 0;
+}
+
+static int asids_init(void)
+{
+	u32 bits = get_cpu_asid_bits();
+
+	if (!asid_allocator_init(&asid_info, bits, ASID_PER_CONTEXT))
+		panic("Unable to initialize ASID allocator for %lu ASIDs\n",
+		      1UL << bits);
+
+	asid_info.active = &active_asids;
+	asid_info.reserved = &reserved_asids;
+
 	pr_info("ASID allocator initialised with %lu entries\n",
-		NUM_CTXT_ASIDS(info));
+		NUM_CTXT_ASIDS(&asid_info));
+
 	return 0;
 }
 early_initcall(asids_init);
-- 
2.11.0


^ permalink raw reply related

* [RFC v2 06/14] arm64/mm: Store the number of asid allocated per context
From: Julien Grall @ 2019-06-20 13:06 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

Currently the number of ASID allocated per context is determined at
compilation time. As the algorithm is becoming generic, the user may
want to instantiate the ASID allocator multiple time with different
number of ASID allocated.

Add a field in asid_info to track the number ASID allocated per context.
This is stored in term of shift amount to avoid division in the code.

This means the number of ASID allocated per context should be a power of
two.

At the same time rename NUM_USERS_ASIDS to NUM_CTXT_ASIDS to make the
name more generic.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index a9cc59288b08..d128f02644b0 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -37,6 +37,8 @@ static struct asid_info
 	raw_spinlock_t		lock;
 	/* Which CPU requires context flush on next call */
 	cpumask_t		flush_pending;
+	/* Number of ASID allocated by context (shift value) */
+	unsigned int		ctxt_shift;
 } asid_info;
 
 #define active_asid(info, cpu)	*per_cpu_ptr((info)->active, cpu)
@@ -49,15 +51,15 @@ static DEFINE_PER_CPU(u64, reserved_asids);
 #define ASID_FIRST_VERSION(info)	(1UL << ((info)->bits))
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info) >> 1)
-#define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> 1)
-#define idx2asid(info, idx)		(((idx) << 1) & ~ASID_MASK(info))
+#define ASID_PER_CONTEXT		2
 #else
-#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info))
-#define asid2idx(info, asid)		((asid) & ~ASID_MASK(info))
-#define idx2asid(info, idx)		asid2idx(info, idx)
+#define ASID_PER_CONTEXT		1
 #endif
 
+#define NUM_CTXT_ASIDS(info)		(ASID_FIRST_VERSION(info) >> (info)->ctxt_shift)
+#define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> (info)->ctxt_shift)
+#define idx2asid(info, idx)		(((idx) << (info)->ctxt_shift) & ~ASID_MASK(info))
+
 /* Get the ASIDBits supported by the current CPU */
 static u32 get_cpu_asid_bits(void)
 {
@@ -102,7 +104,7 @@ static void flush_context(struct asid_info *info)
 	u64 asid;
 
 	/* Update the list of reserved ASIDs and the ASID bitmap. */
-	bitmap_clear(info->map, 0, NUM_USER_ASIDS(info));
+	bitmap_clear(info->map, 0, NUM_CTXT_ASIDS(info));
 
 	for_each_possible_cpu(i) {
 		asid = atomic64_xchg_relaxed(&active_asid(info, i), 0);
@@ -182,8 +184,8 @@ static u64 new_context(struct asid_info *info, atomic64_t *pasid)
 	 * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd
 	 * pairs.
 	 */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), cur_idx);
-	if (asid != NUM_USER_ASIDS(info))
+	asid = find_next_zero_bit(info->map, NUM_CTXT_ASIDS(info), cur_idx);
+	if (asid != NUM_CTXT_ASIDS(info))
 		goto set_asid;
 
 	/* We're out of ASIDs, so increment the global generation count */
@@ -192,7 +194,7 @@ static u64 new_context(struct asid_info *info, atomic64_t *pasid)
 	flush_context(info);
 
 	/* We have more ASIDs than CPUs, so this will always succeed */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), 1);
+	asid = find_next_zero_bit(info->map, NUM_CTXT_ASIDS(info), 1);
 
 set_asid:
 	__set_bit(asid, info->map);
@@ -272,17 +274,18 @@ static int asids_init(void)
 	struct asid_info *info = &asid_info;
 
 	info->bits = get_cpu_asid_bits();
+	info->ctxt_shift = ilog2(ASID_PER_CONTEXT);
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
 	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
 	 */
-	WARN_ON(NUM_USER_ASIDS(info) - 1 <= num_possible_cpus());
+	WARN_ON(NUM_CTXT_ASIDS(info) - 1 <= num_possible_cpus());
 	atomic64_set(&info->generation, ASID_FIRST_VERSION(info));
-	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS(info)),
+	info->map = kcalloc(BITS_TO_LONGS(NUM_CTXT_ASIDS(info)),
 			    sizeof(*info->map), GFP_KERNEL);
 	if (!info->map)
 		panic("Failed to allocate bitmap for %lu ASIDs\n",
-		      NUM_USER_ASIDS(info));
+		      NUM_CTXT_ASIDS(info));
 
 	info->active = &active_asids;
 	info->reserved = &reserved_asids;
@@ -290,7 +293,7 @@ static int asids_init(void)
 	raw_spin_lock_init(&info->lock);
 
 	pr_info("ASID allocator initialised with %lu entries\n",
-		NUM_USER_ASIDS(info));
+		NUM_CTXT_ASIDS(info));
 	return 0;
 }
 early_initcall(asids_init);
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [thud][PATCH] glmark2: specify dependency on libgbm
From: Anand Balagopalakrishnan @ 2019-06-20 13:05 UTC (permalink / raw)
  To: meta-arago
In-Reply-To: <1560958508-141402-2-git-send-email-anandb@ti.com>

Signed-off-by: Anand Balagopalakrishnan <anandb@ti.com>
---
 meta-arago-extras/recipes-benchmark/glmark2/glmark2_git.bb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/meta-arago-extras/recipes-benchmark/glmark2/glmark2_git.bb b/meta-arago-extras/recipes-benchmark/glmark2/glmark2_git.bb
index d7744ad..bc83358 100644
--- a/meta-arago-extras/recipes-benchmark/glmark2/glmark2_git.bb
+++ b/meta-arago-extras/recipes-benchmark/glmark2/glmark2_git.bb
@@ -36,7 +36,7 @@ CXXFLAGS += "-std=c++11"
 PACKAGECONFIG[x11-gl] = ",,virtual/libgl virtual/libx11"
 PACKAGECONFIG[x11-gles2] = ",,virtual/libgles2 virtual/libx11"
 PACKAGECONFIG[drm-gl] = ",,virtual/libgl libdrm"
-PACKAGECONFIG[drm-gles2] = ",,virtual/libgles2 libdrm"
+PACKAGECONFIG[drm-gles2] = ",,virtual/libgles2 libdrm virtual/libgbm"
 PACKAGECONFIG[wayland-gl] = ",,virtual/libgl wayland"
 PACKAGECONFIG[wayland-gles2] = ",,virtual/libgles2 wayland"
 
-- 
1.9.1



^ permalink raw reply related

* [RFC v2 05/14] arm64/mm: Remove dependency on MM in new_context
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: james.morse, marc.zyngier, julien.thierry, suzuki.poulose,
	catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

The function new_context will be part of a generic ASID allocator. At
the moment, the MM structure is only used to fetch the ASID.

To remove the dependency on MM, it is possible to just pass a pointer to
the current ASID.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 6457a9310fe4..a9cc59288b08 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -151,10 +151,10 @@ static bool check_update_reserved_asid(struct asid_info *info, u64 asid,
 	return hit;
 }
 
-static u64 new_context(struct asid_info *info, struct mm_struct *mm)
+static u64 new_context(struct asid_info *info, atomic64_t *pasid)
 {
 	static u32 cur_idx = 1;
-	u64 asid = atomic64_read(&mm->context.id);
+	u64 asid = atomic64_read(pasid);
 	u64 generation = atomic64_read(&info->generation);
 
 	if (asid != 0) {
@@ -236,7 +236,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	/* Check that our ASID belongs to the current generation. */
 	asid = atomic64_read(&mm->context.id);
 	if ((asid ^ atomic64_read(&info->generation)) >> info->bits) {
-		asid = new_context(info, mm);
+		asid = new_context(info, &mm->context.id);
 		atomic64_set(&mm->context.id, asid);
 	}
 
-- 
2.11.0


^ permalink raw reply related

* [RFC v2 05/14] arm64/mm: Remove dependency on MM in new_context
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

The function new_context will be part of a generic ASID allocator. At
the moment, the MM structure is only used to fetch the ASID.

To remove the dependency on MM, it is possible to just pass a pointer to
the current ASID.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 6457a9310fe4..a9cc59288b08 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -151,10 +151,10 @@ static bool check_update_reserved_asid(struct asid_info *info, u64 asid,
 	return hit;
 }
 
-static u64 new_context(struct asid_info *info, struct mm_struct *mm)
+static u64 new_context(struct asid_info *info, atomic64_t *pasid)
 {
 	static u32 cur_idx = 1;
-	u64 asid = atomic64_read(&mm->context.id);
+	u64 asid = atomic64_read(pasid);
 	u64 generation = atomic64_read(&info->generation);
 
 	if (asid != 0) {
@@ -236,7 +236,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	/* Check that our ASID belongs to the current generation. */
 	asid = atomic64_read(&mm->context.id);
 	if ((asid ^ atomic64_read(&info->generation)) >> info->bits) {
-		asid = new_context(info, mm);
+		asid = new_context(info, &mm->context.id);
 		atomic64_set(&mm->context.id, asid);
 	}
 
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 06/14] arm64/mm: Store the number of asid allocated per context
From: Julien Grall @ 2019-06-20 13:06 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: james.morse, marc.zyngier, julien.thierry, suzuki.poulose,
	catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

Currently the number of ASID allocated per context is determined at
compilation time. As the algorithm is becoming generic, the user may
want to instantiate the ASID allocator multiple time with different
number of ASID allocated.

Add a field in asid_info to track the number ASID allocated per context.
This is stored in term of shift amount to avoid division in the code.

This means the number of ASID allocated per context should be a power of
two.

At the same time rename NUM_USERS_ASIDS to NUM_CTXT_ASIDS to make the
name more generic.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index a9cc59288b08..d128f02644b0 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -37,6 +37,8 @@ static struct asid_info
 	raw_spinlock_t		lock;
 	/* Which CPU requires context flush on next call */
 	cpumask_t		flush_pending;
+	/* Number of ASID allocated by context (shift value) */
+	unsigned int		ctxt_shift;
 } asid_info;
 
 #define active_asid(info, cpu)	*per_cpu_ptr((info)->active, cpu)
@@ -49,15 +51,15 @@ static DEFINE_PER_CPU(u64, reserved_asids);
 #define ASID_FIRST_VERSION(info)	(1UL << ((info)->bits))
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info) >> 1)
-#define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> 1)
-#define idx2asid(info, idx)		(((idx) << 1) & ~ASID_MASK(info))
+#define ASID_PER_CONTEXT		2
 #else
-#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info))
-#define asid2idx(info, asid)		((asid) & ~ASID_MASK(info))
-#define idx2asid(info, idx)		asid2idx(info, idx)
+#define ASID_PER_CONTEXT		1
 #endif
 
+#define NUM_CTXT_ASIDS(info)		(ASID_FIRST_VERSION(info) >> (info)->ctxt_shift)
+#define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> (info)->ctxt_shift)
+#define idx2asid(info, idx)		(((idx) << (info)->ctxt_shift) & ~ASID_MASK(info))
+
 /* Get the ASIDBits supported by the current CPU */
 static u32 get_cpu_asid_bits(void)
 {
@@ -102,7 +104,7 @@ static void flush_context(struct asid_info *info)
 	u64 asid;
 
 	/* Update the list of reserved ASIDs and the ASID bitmap. */
-	bitmap_clear(info->map, 0, NUM_USER_ASIDS(info));
+	bitmap_clear(info->map, 0, NUM_CTXT_ASIDS(info));
 
 	for_each_possible_cpu(i) {
 		asid = atomic64_xchg_relaxed(&active_asid(info, i), 0);
@@ -182,8 +184,8 @@ static u64 new_context(struct asid_info *info, atomic64_t *pasid)
 	 * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd
 	 * pairs.
 	 */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), cur_idx);
-	if (asid != NUM_USER_ASIDS(info))
+	asid = find_next_zero_bit(info->map, NUM_CTXT_ASIDS(info), cur_idx);
+	if (asid != NUM_CTXT_ASIDS(info))
 		goto set_asid;
 
 	/* We're out of ASIDs, so increment the global generation count */
@@ -192,7 +194,7 @@ static u64 new_context(struct asid_info *info, atomic64_t *pasid)
 	flush_context(info);
 
 	/* We have more ASIDs than CPUs, so this will always succeed */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), 1);
+	asid = find_next_zero_bit(info->map, NUM_CTXT_ASIDS(info), 1);
 
 set_asid:
 	__set_bit(asid, info->map);
@@ -272,17 +274,18 @@ static int asids_init(void)
 	struct asid_info *info = &asid_info;
 
 	info->bits = get_cpu_asid_bits();
+	info->ctxt_shift = ilog2(ASID_PER_CONTEXT);
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
 	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
 	 */
-	WARN_ON(NUM_USER_ASIDS(info) - 1 <= num_possible_cpus());
+	WARN_ON(NUM_CTXT_ASIDS(info) - 1 <= num_possible_cpus());
 	atomic64_set(&info->generation, ASID_FIRST_VERSION(info));
-	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS(info)),
+	info->map = kcalloc(BITS_TO_LONGS(NUM_CTXT_ASIDS(info)),
 			    sizeof(*info->map), GFP_KERNEL);
 	if (!info->map)
 		panic("Failed to allocate bitmap for %lu ASIDs\n",
-		      NUM_USER_ASIDS(info));
+		      NUM_CTXT_ASIDS(info));
 
 	info->active = &active_asids;
 	info->reserved = &reserved_asids;
@@ -290,7 +293,7 @@ static int asids_init(void)
 	raw_spin_lock_init(&info->lock);
 
 	pr_info("ASID allocator initialised with %lu entries\n",
-		NUM_USER_ASIDS(info));
+		NUM_CTXT_ASIDS(info));
 	return 0;
 }
 early_initcall(asids_init);
-- 
2.11.0


^ permalink raw reply related

* [RFC v2 04/14] arm64/mm: Move the variable lock and tlb_flush_pending to asid_info
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

The variables lock and tlb_flush_pending holds information for a given
ASID allocator. So move them to the asid_info structure.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 7883347ece52..6457a9310fe4 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -27,8 +27,6 @@
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 
-static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
-
 static struct asid_info
 {
 	atomic64_t	generation;
@@ -36,6 +34,9 @@ static struct asid_info
 	atomic64_t __percpu	*active;
 	u64 __percpu		*reserved;
 	u32			bits;
+	raw_spinlock_t		lock;
+	/* Which CPU requires context flush on next call */
+	cpumask_t		flush_pending;
 } asid_info;
 
 #define active_asid(info, cpu)	*per_cpu_ptr((info)->active, cpu)
@@ -44,8 +45,6 @@ static struct asid_info
 static DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 
-static cpumask_t tlb_flush_pending;
-
 #define ASID_MASK(info)			(~GENMASK((info)->bits - 1, 0))
 #define ASID_FIRST_VERSION(info)	(1UL << ((info)->bits))
 
@@ -124,7 +123,7 @@ static void flush_context(struct asid_info *info)
 	 * Queue a TLB invalidation for each CPU to perform on next
 	 * context-switch
 	 */
-	cpumask_setall(&tlb_flush_pending);
+	cpumask_setall(&info->flush_pending);
 }
 
 static bool check_update_reserved_asid(struct asid_info *info, u64 asid,
@@ -233,7 +232,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 				     old_active_asid, asid))
 		goto switch_mm_fastpath;
 
-	raw_spin_lock_irqsave(&cpu_asid_lock, flags);
+	raw_spin_lock_irqsave(&info->lock, flags);
 	/* Check that our ASID belongs to the current generation. */
 	asid = atomic64_read(&mm->context.id);
 	if ((asid ^ atomic64_read(&info->generation)) >> info->bits) {
@@ -241,11 +240,11 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 		atomic64_set(&mm->context.id, asid);
 	}
 
-	if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
+	if (cpumask_test_and_clear_cpu(cpu, &info->flush_pending))
 		local_flush_tlb_all();
 
 	atomic64_set(&active_asid(info, cpu), asid);
-	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
+	raw_spin_unlock_irqrestore(&info->lock, flags);
 
 switch_mm_fastpath:
 
@@ -288,6 +287,8 @@ static int asids_init(void)
 	info->active = &active_asids;
 	info->reserved = &reserved_asids;
 
+	raw_spin_lock_init(&info->lock);
+
 	pr_info("ASID allocator initialised with %lu entries\n",
 		NUM_USER_ASIDS(info));
 	return 0;
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 03/14] arm64/mm: Move bits to asid_info
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: james.morse, marc.zyngier, julien.thierry, suzuki.poulose,
	catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

The variable bits hold information for a given ASID allocator. So move
it to the asid_info structure.

Because most of the macros were relying on bits, they are now taking an
extra parameter that is a pointer to the asid_info structure.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 59 +++++++++++++++++++++++++------------------------
 1 file changed, 30 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 6bacfc295f6e..7883347ece52 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -27,7 +27,6 @@
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 
-static u32 asid_bits;
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 
 static struct asid_info
@@ -36,6 +35,7 @@ static struct asid_info
 	unsigned long	*map;
 	atomic64_t __percpu	*active;
 	u64 __percpu		*reserved;
+	u32			bits;
 } asid_info;
 
 #define active_asid(info, cpu)	*per_cpu_ptr((info)->active, cpu)
@@ -46,17 +46,17 @@ static DEFINE_PER_CPU(u64, reserved_asids);
 
 static cpumask_t tlb_flush_pending;
 
-#define ASID_MASK		(~GENMASK(asid_bits - 1, 0))
-#define ASID_FIRST_VERSION	(1UL << asid_bits)
+#define ASID_MASK(info)			(~GENMASK((info)->bits - 1, 0))
+#define ASID_FIRST_VERSION(info)	(1UL << ((info)->bits))
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-#define NUM_USER_ASIDS		(ASID_FIRST_VERSION >> 1)
-#define asid2idx(asid)		(((asid) & ~ASID_MASK) >> 1)
-#define idx2asid(idx)		(((idx) << 1) & ~ASID_MASK)
+#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info) >> 1)
+#define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> 1)
+#define idx2asid(info, idx)		(((idx) << 1) & ~ASID_MASK(info))
 #else
-#define NUM_USER_ASIDS		(ASID_FIRST_VERSION)
-#define asid2idx(asid)		((asid) & ~ASID_MASK)
-#define idx2asid(idx)		asid2idx(idx)
+#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info))
+#define asid2idx(info, asid)		((asid) & ~ASID_MASK(info))
+#define idx2asid(info, idx)		asid2idx(info, idx)
 #endif
 
 /* Get the ASIDBits supported by the current CPU */
@@ -86,13 +86,13 @@ void verify_cpu_asid_bits(void)
 {
 	u32 asid = get_cpu_asid_bits();
 
-	if (asid < asid_bits) {
+	if (asid < asid_info.bits) {
 		/*
 		 * We cannot decrease the ASID size at runtime, so panic if we support
 		 * fewer ASID bits than the boot CPU.
 		 */
 		pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n",
-				smp_processor_id(), asid, asid_bits);
+				smp_processor_id(), asid, asid_info.bits);
 		cpu_panic_kernel();
 	}
 }
@@ -103,7 +103,7 @@ static void flush_context(struct asid_info *info)
 	u64 asid;
 
 	/* Update the list of reserved ASIDs and the ASID bitmap. */
-	bitmap_clear(info->map, 0, NUM_USER_ASIDS);
+	bitmap_clear(info->map, 0, NUM_USER_ASIDS(info));
 
 	for_each_possible_cpu(i) {
 		asid = atomic64_xchg_relaxed(&active_asid(info, i), 0);
@@ -116,7 +116,7 @@ static void flush_context(struct asid_info *info)
 		 */
 		if (asid == 0)
 			asid = reserved_asid(info, i);
-		__set_bit(asid2idx(asid), info->map);
+		__set_bit(asid2idx(info, asid), info->map);
 		reserved_asid(info, i) = asid;
 	}
 
@@ -159,7 +159,7 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 	u64 generation = atomic64_read(&info->generation);
 
 	if (asid != 0) {
-		u64 newasid = generation | (asid & ~ASID_MASK);
+		u64 newasid = generation | (asid & ~ASID_MASK(info));
 
 		/*
 		 * If our current ASID was active during a rollover, we
@@ -172,7 +172,7 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 		 * We had a valid ASID in a previous life, so try to re-use
 		 * it if possible.
 		 */
-		if (!__test_and_set_bit(asid2idx(asid), info->map))
+		if (!__test_and_set_bit(asid2idx(info, asid), info->map))
 			return newasid;
 	}
 
@@ -183,22 +183,22 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 	 * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd
 	 * pairs.
 	 */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS, cur_idx);
-	if (asid != NUM_USER_ASIDS)
+	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), cur_idx);
+	if (asid != NUM_USER_ASIDS(info))
 		goto set_asid;
 
 	/* We're out of ASIDs, so increment the global generation count */
-	generation = atomic64_add_return_relaxed(ASID_FIRST_VERSION,
+	generation = atomic64_add_return_relaxed(ASID_FIRST_VERSION(info),
 						 &info->generation);
 	flush_context(info);
 
 	/* We have more ASIDs than CPUs, so this will always succeed */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS, 1);
+	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), 1);
 
 set_asid:
 	__set_bit(asid, info->map);
 	cur_idx = asid;
-	return idx2asid(asid) | generation;
+	return idx2asid(info, asid) | generation;
 }
 
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
@@ -228,7 +228,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	 */
 	old_active_asid = atomic64_read(&active_asid(info, cpu));
 	if (old_active_asid &&
-	    !((asid ^ atomic64_read(&info->generation)) >> asid_bits) &&
+	    !((asid ^ atomic64_read(&info->generation)) >> info->bits) &&
 	    atomic64_cmpxchg_relaxed(&active_asid(info, cpu),
 				     old_active_asid, asid))
 		goto switch_mm_fastpath;
@@ -236,7 +236,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	raw_spin_lock_irqsave(&cpu_asid_lock, flags);
 	/* Check that our ASID belongs to the current generation. */
 	asid = atomic64_read(&mm->context.id);
-	if ((asid ^ atomic64_read(&info->generation)) >> asid_bits) {
+	if ((asid ^ atomic64_read(&info->generation)) >> info->bits) {
 		asid = new_context(info, mm);
 		atomic64_set(&mm->context.id, asid);
 	}
@@ -272,23 +272,24 @@ static int asids_init(void)
 {
 	struct asid_info *info = &asid_info;
 
-	asid_bits = get_cpu_asid_bits();
+	info->bits = get_cpu_asid_bits();
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
 	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
 	 */
-	WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
-	atomic64_set(&info->generation, ASID_FIRST_VERSION);
-	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*info->map),
-			    GFP_KERNEL);
+	WARN_ON(NUM_USER_ASIDS(info) - 1 <= num_possible_cpus());
+	atomic64_set(&info->generation, ASID_FIRST_VERSION(info));
+	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS(info)),
+			    sizeof(*info->map), GFP_KERNEL);
 	if (!info->map)
 		panic("Failed to allocate bitmap for %lu ASIDs\n",
-		      NUM_USER_ASIDS);
+		      NUM_USER_ASIDS(info));
 
 	info->active = &active_asids;
 	info->reserved = &reserved_asids;
 
-	pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
+	pr_info("ASID allocator initialised with %lu entries\n",
+		NUM_USER_ASIDS(info));
 	return 0;
 }
 early_initcall(asids_init);
-- 
2.11.0


^ permalink raw reply related

* [RFC v2 03/14] arm64/mm: Move bits to asid_info
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

The variable bits hold information for a given ASID allocator. So move
it to the asid_info structure.

Because most of the macros were relying on bits, they are now taking an
extra parameter that is a pointer to the asid_info structure.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 59 +++++++++++++++++++++++++------------------------
 1 file changed, 30 insertions(+), 29 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 6bacfc295f6e..7883347ece52 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -27,7 +27,6 @@
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 
-static u32 asid_bits;
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 
 static struct asid_info
@@ -36,6 +35,7 @@ static struct asid_info
 	unsigned long	*map;
 	atomic64_t __percpu	*active;
 	u64 __percpu		*reserved;
+	u32			bits;
 } asid_info;
 
 #define active_asid(info, cpu)	*per_cpu_ptr((info)->active, cpu)
@@ -46,17 +46,17 @@ static DEFINE_PER_CPU(u64, reserved_asids);
 
 static cpumask_t tlb_flush_pending;
 
-#define ASID_MASK		(~GENMASK(asid_bits - 1, 0))
-#define ASID_FIRST_VERSION	(1UL << asid_bits)
+#define ASID_MASK(info)			(~GENMASK((info)->bits - 1, 0))
+#define ASID_FIRST_VERSION(info)	(1UL << ((info)->bits))
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-#define NUM_USER_ASIDS		(ASID_FIRST_VERSION >> 1)
-#define asid2idx(asid)		(((asid) & ~ASID_MASK) >> 1)
-#define idx2asid(idx)		(((idx) << 1) & ~ASID_MASK)
+#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info) >> 1)
+#define asid2idx(info, asid)		(((asid) & ~ASID_MASK(info)) >> 1)
+#define idx2asid(info, idx)		(((idx) << 1) & ~ASID_MASK(info))
 #else
-#define NUM_USER_ASIDS		(ASID_FIRST_VERSION)
-#define asid2idx(asid)		((asid) & ~ASID_MASK)
-#define idx2asid(idx)		asid2idx(idx)
+#define NUM_USER_ASIDS(info)		(ASID_FIRST_VERSION(info))
+#define asid2idx(info, asid)		((asid) & ~ASID_MASK(info))
+#define idx2asid(info, idx)		asid2idx(info, idx)
 #endif
 
 /* Get the ASIDBits supported by the current CPU */
@@ -86,13 +86,13 @@ void verify_cpu_asid_bits(void)
 {
 	u32 asid = get_cpu_asid_bits();
 
-	if (asid < asid_bits) {
+	if (asid < asid_info.bits) {
 		/*
 		 * We cannot decrease the ASID size at runtime, so panic if we support
 		 * fewer ASID bits than the boot CPU.
 		 */
 		pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n",
-				smp_processor_id(), asid, asid_bits);
+				smp_processor_id(), asid, asid_info.bits);
 		cpu_panic_kernel();
 	}
 }
@@ -103,7 +103,7 @@ static void flush_context(struct asid_info *info)
 	u64 asid;
 
 	/* Update the list of reserved ASIDs and the ASID bitmap. */
-	bitmap_clear(info->map, 0, NUM_USER_ASIDS);
+	bitmap_clear(info->map, 0, NUM_USER_ASIDS(info));
 
 	for_each_possible_cpu(i) {
 		asid = atomic64_xchg_relaxed(&active_asid(info, i), 0);
@@ -116,7 +116,7 @@ static void flush_context(struct asid_info *info)
 		 */
 		if (asid == 0)
 			asid = reserved_asid(info, i);
-		__set_bit(asid2idx(asid), info->map);
+		__set_bit(asid2idx(info, asid), info->map);
 		reserved_asid(info, i) = asid;
 	}
 
@@ -159,7 +159,7 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 	u64 generation = atomic64_read(&info->generation);
 
 	if (asid != 0) {
-		u64 newasid = generation | (asid & ~ASID_MASK);
+		u64 newasid = generation | (asid & ~ASID_MASK(info));
 
 		/*
 		 * If our current ASID was active during a rollover, we
@@ -172,7 +172,7 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 		 * We had a valid ASID in a previous life, so try to re-use
 		 * it if possible.
 		 */
-		if (!__test_and_set_bit(asid2idx(asid), info->map))
+		if (!__test_and_set_bit(asid2idx(info, asid), info->map))
 			return newasid;
 	}
 
@@ -183,22 +183,22 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 	 * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd
 	 * pairs.
 	 */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS, cur_idx);
-	if (asid != NUM_USER_ASIDS)
+	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), cur_idx);
+	if (asid != NUM_USER_ASIDS(info))
 		goto set_asid;
 
 	/* We're out of ASIDs, so increment the global generation count */
-	generation = atomic64_add_return_relaxed(ASID_FIRST_VERSION,
+	generation = atomic64_add_return_relaxed(ASID_FIRST_VERSION(info),
 						 &info->generation);
 	flush_context(info);
 
 	/* We have more ASIDs than CPUs, so this will always succeed */
-	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS, 1);
+	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS(info), 1);
 
 set_asid:
 	__set_bit(asid, info->map);
 	cur_idx = asid;
-	return idx2asid(asid) | generation;
+	return idx2asid(info, asid) | generation;
 }
 
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
@@ -228,7 +228,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	 */
 	old_active_asid = atomic64_read(&active_asid(info, cpu));
 	if (old_active_asid &&
-	    !((asid ^ atomic64_read(&info->generation)) >> asid_bits) &&
+	    !((asid ^ atomic64_read(&info->generation)) >> info->bits) &&
 	    atomic64_cmpxchg_relaxed(&active_asid(info, cpu),
 				     old_active_asid, asid))
 		goto switch_mm_fastpath;
@@ -236,7 +236,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	raw_spin_lock_irqsave(&cpu_asid_lock, flags);
 	/* Check that our ASID belongs to the current generation. */
 	asid = atomic64_read(&mm->context.id);
-	if ((asid ^ atomic64_read(&info->generation)) >> asid_bits) {
+	if ((asid ^ atomic64_read(&info->generation)) >> info->bits) {
 		asid = new_context(info, mm);
 		atomic64_set(&mm->context.id, asid);
 	}
@@ -272,23 +272,24 @@ static int asids_init(void)
 {
 	struct asid_info *info = &asid_info;
 
-	asid_bits = get_cpu_asid_bits();
+	info->bits = get_cpu_asid_bits();
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
 	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
 	 */
-	WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
-	atomic64_set(&info->generation, ASID_FIRST_VERSION);
-	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*info->map),
-			    GFP_KERNEL);
+	WARN_ON(NUM_USER_ASIDS(info) - 1 <= num_possible_cpus());
+	atomic64_set(&info->generation, ASID_FIRST_VERSION(info));
+	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS(info)),
+			    sizeof(*info->map), GFP_KERNEL);
 	if (!info->map)
 		panic("Failed to allocate bitmap for %lu ASIDs\n",
-		      NUM_USER_ASIDS);
+		      NUM_USER_ASIDS(info));
 
 	info->active = &active_asids;
 	info->reserved = &reserved_asids;
 
-	pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
+	pr_info("ASID allocator initialised with %lu entries\n",
+		NUM_USER_ASIDS(info));
 	return 0;
 }
 early_initcall(asids_init);
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 02/14] arm64/mm: Move active_asids and reserved_asids to asid_info
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

The variables active_asids and reserved_asids hold information for a
given ASID allocator. So move them to the structure asid_info.

At the same time, introduce wrappers to access the active and reserved
ASIDs to make the code clearer.

Signed-off-by: Julien Grall <julien.grall@arm.com>
---
 arch/arm64/mm/context.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 8167c369172d..6bacfc295f6e 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -34,10 +34,16 @@ static struct asid_info
 {
 	atomic64_t	generation;
 	unsigned long	*map;
+	atomic64_t __percpu	*active;
+	u64 __percpu		*reserved;
 } asid_info;
 
+#define active_asid(info, cpu)	*per_cpu_ptr((info)->active, cpu)
+#define reserved_asid(info, cpu) *per_cpu_ptr((info)->reserved, cpu)
+
 static DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
+
 static cpumask_t tlb_flush_pending;
 
 #define ASID_MASK		(~GENMASK(asid_bits - 1, 0))
@@ -100,7 +106,7 @@ static void flush_context(struct asid_info *info)
 	bitmap_clear(info->map, 0, NUM_USER_ASIDS);
 
 	for_each_possible_cpu(i) {
-		asid = atomic64_xchg_relaxed(&per_cpu(active_asids, i), 0);
+		asid = atomic64_xchg_relaxed(&active_asid(info, i), 0);
 		/*
 		 * If this CPU has already been through a
 		 * rollover, but hasn't run another task in
@@ -109,9 +115,9 @@ static void flush_context(struct asid_info *info)
 		 * the process it is still running.
 		 */
 		if (asid == 0)
-			asid = per_cpu(reserved_asids, i);
+			asid = reserved_asid(info, i);
 		__set_bit(asid2idx(asid), info->map);
-		per_cpu(reserved_asids, i) = asid;
+		reserved_asid(info, i) = asid;
 	}
 
 	/*
@@ -121,7 +127,8 @@ static void flush_context(struct asid_info *info)
 	cpumask_setall(&tlb_flush_pending);
 }
 
-static bool check_update_reserved_asid(u64 asid, u64 newasid)
+static bool check_update_reserved_asid(struct asid_info *info, u64 asid,
+				       u64 newasid)
 {
 	int cpu;
 	bool hit = false;
@@ -136,9 +143,9 @@ static bool check_update_reserved_asid(u64 asid, u64 newasid)
 	 * generation.
 	 */
 	for_each_possible_cpu(cpu) {
-		if (per_cpu(reserved_asids, cpu) == asid) {
+		if (reserved_asid(info, cpu) == asid) {
 			hit = true;
-			per_cpu(reserved_asids, cpu) = newasid;
+			reserved_asid(info, cpu) = newasid;
 		}
 	}
 
@@ -158,7 +165,7 @@ static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 		 * If our current ASID was active during a rollover, we
 		 * can continue to use it and this was just a false alarm.
 		 */
-		if (check_update_reserved_asid(asid, newasid))
+		if (check_update_reserved_asid(info, asid, newasid))
 			return newasid;
 
 		/*
@@ -207,8 +214,8 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 
 	/*
 	 * The memory ordering here is subtle.
-	 * If our active_asids is non-zero and the ASID matches the current
-	 * generation, then we update the active_asids entry with a relaxed
+	 * If our active_asid is non-zero and the ASID matches the current
+	 * generation, then we update the active_asid entry with a relaxed
 	 * cmpxchg. Racing with a concurrent rollover means that either:
 	 *
 	 * - We get a zero back from the cmpxchg and end up waiting on the
@@ -219,10 +226,10 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	 *   relaxed xchg in flush_context will treat us as reserved
 	 *   because atomic RmWs are totally ordered for a given location.
 	 */
-	old_active_asid = atomic64_read(&per_cpu(active_asids, cpu));
+	old_active_asid = atomic64_read(&active_asid(info, cpu));
 	if (old_active_asid &&
 	    !((asid ^ atomic64_read(&info->generation)) >> asid_bits) &&
-	    atomic64_cmpxchg_relaxed(&per_cpu(active_asids, cpu),
+	    atomic64_cmpxchg_relaxed(&active_asid(info, cpu),
 				     old_active_asid, asid))
 		goto switch_mm_fastpath;
 
@@ -237,7 +244,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
 		local_flush_tlb_all();
 
-	atomic64_set(&per_cpu(active_asids, cpu), asid);
+	atomic64_set(&active_asid(info, cpu), asid);
 	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
 switch_mm_fastpath:
@@ -278,6 +285,9 @@ static int asids_init(void)
 		panic("Failed to allocate bitmap for %lu ASIDs\n",
 		      NUM_USER_ASIDS);
 
+	info->active = &active_asids;
+	info->reserved = &reserved_asids;
+
 	pr_info("ASID allocator initialised with %lu entries\n", NUM_USER_ASIDS);
 	return 0;
 }
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 01/14] arm64/mm: Introduce asid_info structure and move asid_generation/asid_map to it
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Julien Grall
In-Reply-To: <20190620130608.17230-1-julien.grall@arm.com>

In an attempt to make the ASID allocator generic, create a new structure
asid_info to store all the information necessary for the allocator.

For now, move the variables asid_generation and asid_map to the new structure
asid_info. Follow-up patches will move more variables.

Note to avoid more renaming aftwards, a local variable 'info' has been
created and is a pointer to the ASID allocator structure.

Signed-off-by: Julien Grall <julien.grall@arm.com>

---
    Changes in v2:
        - Add turn asid_info to a static variable
---
 arch/arm64/mm/context.c | 46 ++++++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 1f0ea2facf24..8167c369172d 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -30,8 +30,11 @@
 static u32 asid_bits;
 static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 
-static atomic64_t asid_generation;
-static unsigned long *asid_map;
+static struct asid_info
+{
+	atomic64_t	generation;
+	unsigned long	*map;
+} asid_info;
 
 static DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
@@ -88,13 +91,13 @@ void verify_cpu_asid_bits(void)
 	}
 }
 
-static void flush_context(void)
+static void flush_context(struct asid_info *info)
 {
 	int i;
 	u64 asid;
 
 	/* Update the list of reserved ASIDs and the ASID bitmap. */
-	bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
+	bitmap_clear(info->map, 0, NUM_USER_ASIDS);
 
 	for_each_possible_cpu(i) {
 		asid = atomic64_xchg_relaxed(&per_cpu(active_asids, i), 0);
@@ -107,7 +110,7 @@ static void flush_context(void)
 		 */
 		if (asid == 0)
 			asid = per_cpu(reserved_asids, i);
-		__set_bit(asid2idx(asid), asid_map);
+		__set_bit(asid2idx(asid), info->map);
 		per_cpu(reserved_asids, i) = asid;
 	}
 
@@ -142,11 +145,11 @@ static bool check_update_reserved_asid(u64 asid, u64 newasid)
 	return hit;
 }
 
-static u64 new_context(struct mm_struct *mm)
+static u64 new_context(struct asid_info *info, struct mm_struct *mm)
 {
 	static u32 cur_idx = 1;
 	u64 asid = atomic64_read(&mm->context.id);
-	u64 generation = atomic64_read(&asid_generation);
+	u64 generation = atomic64_read(&info->generation);
 
 	if (asid != 0) {
 		u64 newasid = generation | (asid & ~ASID_MASK);
@@ -162,7 +165,7 @@ static u64 new_context(struct mm_struct *mm)
 		 * We had a valid ASID in a previous life, so try to re-use
 		 * it if possible.
 		 */
-		if (!__test_and_set_bit(asid2idx(asid), asid_map))
+		if (!__test_and_set_bit(asid2idx(asid), info->map))
 			return newasid;
 	}
 
@@ -173,20 +176,20 @@ static u64 new_context(struct mm_struct *mm)
 	 * a reserved TTBR0 for the init_mm and we allocate ASIDs in even/odd
 	 * pairs.
 	 */
-	asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, cur_idx);
+	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS, cur_idx);
 	if (asid != NUM_USER_ASIDS)
 		goto set_asid;
 
 	/* We're out of ASIDs, so increment the global generation count */
 	generation = atomic64_add_return_relaxed(ASID_FIRST_VERSION,
-						 &asid_generation);
-	flush_context();
+						 &info->generation);
+	flush_context(info);
 
 	/* We have more ASIDs than CPUs, so this will always succeed */
-	asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
+	asid = find_next_zero_bit(info->map, NUM_USER_ASIDS, 1);
 
 set_asid:
-	__set_bit(asid, asid_map);
+	__set_bit(asid, info->map);
 	cur_idx = asid;
 	return idx2asid(asid) | generation;
 }
@@ -195,6 +198,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 {
 	unsigned long flags;
 	u64 asid, old_active_asid;
+	struct asid_info *info = &asid_info;
 
 	if (system_supports_cnp())
 		cpu_set_reserved_ttbr0();
@@ -217,7 +221,7 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	 */
 	old_active_asid = atomic64_read(&per_cpu(active_asids, cpu));
 	if (old_active_asid &&
-	    !((asid ^ atomic64_read(&asid_generation)) >> asid_bits) &&
+	    !((asid ^ atomic64_read(&info->generation)) >> asid_bits) &&
 	    atomic64_cmpxchg_relaxed(&per_cpu(active_asids, cpu),
 				     old_active_asid, asid))
 		goto switch_mm_fastpath;
@@ -225,8 +229,8 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
 	raw_spin_lock_irqsave(&cpu_asid_lock, flags);
 	/* Check that our ASID belongs to the current generation. */
 	asid = atomic64_read(&mm->context.id);
-	if ((asid ^ atomic64_read(&asid_generation)) >> asid_bits) {
-		asid = new_context(mm);
+	if ((asid ^ atomic64_read(&info->generation)) >> asid_bits) {
+		asid = new_context(info, mm);
 		atomic64_set(&mm->context.id, asid);
 	}
 
@@ -259,16 +263,18 @@ asmlinkage void post_ttbr_update_workaround(void)
 
 static int asids_init(void)
 {
+	struct asid_info *info = &asid_info;
+
 	asid_bits = get_cpu_asid_bits();
 	/*
 	 * Expect allocation after rollover to fail if we don't have at least
 	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
 	 */
 	WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
-	atomic64_set(&asid_generation, ASID_FIRST_VERSION);
-	asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*asid_map),
-			   GFP_KERNEL);
-	if (!asid_map)
+	atomic64_set(&info->generation, ASID_FIRST_VERSION);
+	info->map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*info->map),
+			    GFP_KERNEL);
+	if (!info->map)
 		panic("Failed to allocate bitmap for %lu ASIDs\n",
 		      NUM_USER_ASIDS);
 
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related

* [RFC v2 00/14] kvm/arm: Align the VMID allocation with the arm64 ASID one
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: marc.zyngier, catalin.marinas, will.deacon, Russell King,
	Julien Grall

Hi all,

This patch series is moving out the ASID allocator in a separate file in order
to re-use it for the VMID. The benefits are:
    - CPUs are not forced to exit on a roll-over.
    - Context invalidation is now per-CPU rather than
      broadcasted.

There are no performance regression on the fastpath for ASID allocation.
Actually on the hackbench measurement (300 hackbench) it was .7% faster.

The measurement was made on a Seattle based SoC (8 CPUs), with the
number of VMID limited to 4-bit. The test involves running concurrently 40
guests with 2 vCPUs. Each guest will then execute hackbench 5 times
before exiting.

The performance difference (on 5.1-rc1) between the current algo and the
new one are:
    - 2.5% less exit from the guest
    - 22.4% more flush, although they are now local rather than broadcasted
    - 0.11% faster (just for the record)

The ASID allocator rework to make it generic has been divided in multiple
patches to make the review easier.

Compare to the first RFC, Arm is not duplicated most of the code anymore.
Instead, Arm will build the version from Arm64.

A branch with the patch based on 5.2-rc5 can be found:

http://xenbits.xen.org/gitweb/?p=people/julieng/linux-arm.git;a=shortlog;h=refs/heads/vmid-rework/rfc-v2

Best regards,

Cc: Russell King <linux@armlinux.org.uk>

Julien Grall (14):
  arm64/mm: Introduce asid_info structure and move
    asid_generation/asid_map to it
  arm64/mm: Move active_asids and reserved_asids to asid_info
  arm64/mm: Move bits to asid_info
  arm64/mm: Move the variable lock and tlb_flush_pending to asid_info
  arm64/mm: Remove dependency on MM in new_context
  arm64/mm: Store the number of asid allocated per context
  arm64/mm: Introduce NUM_ASIDS
  arm64/mm: Split asid_inits in 2 parts
  arm64/mm: Split the function check_and_switch_context in 3 parts
  arm64/mm: Introduce a callback to flush the local context
  arm64: Move the ASID allocator code in a separate file
  arm64/lib: asid: Allow user to update the context under the lock
  arm/kvm: Introduce a new VMID allocator
  kvm/arm: Align the VMID allocation with the arm64 ASID one

 arch/arm/include/asm/kvm_asm.h    |   2 +-
 arch/arm/include/asm/kvm_host.h   |   5 +-
 arch/arm/include/asm/kvm_hyp.h    |   1 +
 arch/arm/include/asm/lib_asid.h   |  81 +++++++++++++++
 arch/arm/kvm/Makefile             |   1 +
 arch/arm/kvm/hyp/tlb.c            |   8 +-
 arch/arm64/include/asm/kvm_asid.h |   8 ++
 arch/arm64/include/asm/kvm_asm.h  |   2 +-
 arch/arm64/include/asm/kvm_host.h |   5 +-
 arch/arm64/include/asm/lib_asid.h |  81 +++++++++++++++
 arch/arm64/kvm/hyp/tlb.c          |  10 +-
 arch/arm64/lib/Makefile           |   2 +
 arch/arm64/lib/asid.c             | 191 +++++++++++++++++++++++++++++++++++
 arch/arm64/mm/context.c           | 205 ++++++--------------------------------
 virt/kvm/arm/arm.c                | 112 +++++++--------------
 15 files changed, 447 insertions(+), 267 deletions(-)
 create mode 100644 arch/arm/include/asm/lib_asid.h
 create mode 100644 arch/arm64/include/asm/kvm_asid.h
 create mode 100644 arch/arm64/include/asm/lib_asid.h
 create mode 100644 arch/arm64/lib/asid.c

-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply

* [RFC v2 00/14] kvm/arm: Align the VMID allocation with the arm64 ASID one
From: Julien Grall @ 2019-06-20 13:05 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, kvmarm
  Cc: james.morse, marc.zyngier, julien.thierry, suzuki.poulose,
	catalin.marinas, will.deacon, Julien Grall, Russell King

Hi all,

This patch series is moving out the ASID allocator in a separate file in order
to re-use it for the VMID. The benefits are:
    - CPUs are not forced to exit on a roll-over.
    - Context invalidation is now per-CPU rather than
      broadcasted.

There are no performance regression on the fastpath for ASID allocation.
Actually on the hackbench measurement (300 hackbench) it was .7% faster.

The measurement was made on a Seattle based SoC (8 CPUs), with the
number of VMID limited to 4-bit. The test involves running concurrently 40
guests with 2 vCPUs. Each guest will then execute hackbench 5 times
before exiting.

The performance difference (on 5.1-rc1) between the current algo and the
new one are:
    - 2.5% less exit from the guest
    - 22.4% more flush, although they are now local rather than broadcasted
    - 0.11% faster (just for the record)

The ASID allocator rework to make it generic has been divided in multiple
patches to make the review easier.

Compare to the first RFC, Arm is not duplicated most of the code anymore.
Instead, Arm will build the version from Arm64.

A branch with the patch based on 5.2-rc5 can be found:

http://xenbits.xen.org/gitweb/?p=people/julieng/linux-arm.git;a=shortlog;h=refs/heads/vmid-rework/rfc-v2

Best regards,

Cc: Russell King <linux@armlinux.org.uk>

Julien Grall (14):
  arm64/mm: Introduce asid_info structure and move
    asid_generation/asid_map to it
  arm64/mm: Move active_asids and reserved_asids to asid_info
  arm64/mm: Move bits to asid_info
  arm64/mm: Move the variable lock and tlb_flush_pending to asid_info
  arm64/mm: Remove dependency on MM in new_context
  arm64/mm: Store the number of asid allocated per context
  arm64/mm: Introduce NUM_ASIDS
  arm64/mm: Split asid_inits in 2 parts
  arm64/mm: Split the function check_and_switch_context in 3 parts
  arm64/mm: Introduce a callback to flush the local context
  arm64: Move the ASID allocator code in a separate file
  arm64/lib: asid: Allow user to update the context under the lock
  arm/kvm: Introduce a new VMID allocator
  kvm/arm: Align the VMID allocation with the arm64 ASID one

 arch/arm/include/asm/kvm_asm.h    |   2 +-
 arch/arm/include/asm/kvm_host.h   |   5 +-
 arch/arm/include/asm/kvm_hyp.h    |   1 +
 arch/arm/include/asm/lib_asid.h   |  81 +++++++++++++++
 arch/arm/kvm/Makefile             |   1 +
 arch/arm/kvm/hyp/tlb.c            |   8 +-
 arch/arm64/include/asm/kvm_asid.h |   8 ++
 arch/arm64/include/asm/kvm_asm.h  |   2 +-
 arch/arm64/include/asm/kvm_host.h |   5 +-
 arch/arm64/include/asm/lib_asid.h |  81 +++++++++++++++
 arch/arm64/kvm/hyp/tlb.c          |  10 +-
 arch/arm64/lib/Makefile           |   2 +
 arch/arm64/lib/asid.c             | 191 +++++++++++++++++++++++++++++++++++
 arch/arm64/mm/context.c           | 205 ++++++--------------------------------
 virt/kvm/arm/arm.c                | 112 +++++++--------------
 15 files changed, 447 insertions(+), 267 deletions(-)
 create mode 100644 arch/arm/include/asm/lib_asid.h
 create mode 100644 arch/arm64/include/asm/kvm_asid.h
 create mode 100644 arch/arm64/include/asm/lib_asid.h
 create mode 100644 arch/arm64/lib/asid.c

-- 
2.11.0


^ permalink raw reply

* Re: [PATCH 2/3] crypto: inside-secure - add support for PCI based FPGA development board
From: Antoine Tenart @ 2019-06-20 13:06 UTC (permalink / raw)
  To: Pascal Van Leeuwen
  Cc: Antoine Tenart, Pascal van Leeuwen, linux-crypto@vger.kernel.org,
	herbert@gondor.apana.org.au, davem@davemloft.net
In-Reply-To: <AM6PR09MB352354E57F4CB4C9FD6F39B4D2E50@AM6PR09MB3523.eurprd09.prod.outlook.com>

Hi Pascal,

On Wed, Jun 19, 2019 at 02:22:19PM +0000, Pascal Van Leeuwen wrote:
> > From: Antoine Tenart <antoine.tenart@bootlin.com>
> > On Tue, Jun 18, 2019 at 07:56:23AM +0200, Pascal van Leeuwen wrote:
> > >
> > >  			/* Fallback to the old firmware location for the
> > > @@ -294,6 +291,9 @@ static int safexcel_hw_init(struct safexcel_crypto_priv *priv)
> > >
> > > +	dev_info(priv->dev, "EIP(1)97 HW init: burst size %d beats, using %d pipe(s) and %d
> > ring(s)",
> > > +			16, priv->config.pes, priv->config.rings);
> > 
> > Adding custom messages in the kernel log has to be done carefully.
> > Although it's not considered stable it could be difficult to rework
> > later on. Also, if all driver were to print custom messages the log
> > would be very hard to read. But you can also argue that a single message
> > when probing a driver is also done in other drivers.
> > 
> Hmm ... don't know what the rules for logging are exactly, but from my
> perspective, I'm dealing with a zillion different HW configurations so 
> some feedback whether the driver detected the *correct* HW parameters - 
> or actually, whether I stuffed the correct image into my FPGA :o) - is 
> very convenient to have. And not just for my local development, but also 
> to debug deployments in the field at customer sites.

I understand it can be convenient, it's just a matter of having a
logging message for you that will end up in many builds for many users.
They do not necessarily have the same needs. So it's a matter of
compromise, one or two messages at boot can be OK, more is likely to
become an issue.

> Also, looking at my log, there's other drivers that are similarly 
> (or even more) verbose.

There are *always* other examples in the kernel :)

> If it's a really considered a problem, I could make it dev_dbg?

Sure. I would say adding one message at boot like this one seems OK. But
the others would need to be debugging messages.

> > For this one particularly, the probe could fail later on. So if we were
> > to add this output, it should be done at the very end of the probe.
> > 
> I'm in doubt about this one. I understand that you want to reduce the
> logging in that case, but at the same time that message can convey
> information as to WHY the probing fails later on ...

If the drivers fails to probe, there will be other messages. In that
case is this one really needed? I'm not sure.

> i.e. if it detects, say, 4 pipes on a device that, in fact, only has
> 2, then that may be the very reason for the FW init to fail later on.

In case of failure you'll need anyway to debug and understand what's
going on. By adding new prints, or enabling debugging messages.

> > > -static int safexcel_request_ring_irq(struct platform_device *pdev, const char *name,
> > > +static int safexcel_request_ring_irq(void *pdev, int irqid,
> > > +				     int is_pci_dev,
> > 
> > You could probably use the DEVICE_IS_PCI flag instead.
> > 
> I'm not currently passing priv to that function, so I can't access
> priv->version directly. I could pass a priv pointer instead and use
> the flag, but passing a bool constant seemed to be more efficient?

That right, whatever you prefer then.

> > > +static int safexcel_probe_generic(void *pdev,
> > > +				  struct safexcel_crypto_priv *priv,
> > > +				  int is_pci_dev)
> > >  {
> > 
> > > +	if (IS_ENABLED(CONFIG_PCI) && (priv->version & DEVICE_IS_PCI)) {
> > 
> > DEVICE_IS_PCI should be set in ->flags, not ->version.
> > 
> As far as I could tell from the existing code, "version" was
> a highlevel indication of the device *type* (EIP97/EIP197B/D)
> while flags was more about low-level *features*.

Using the same argument I would say the way the device is accessed is
very run-time dependent, and it has nothing to do with the version of
the h/w (the same engine could be accessed through different ways given
the platform).

Maybe the name 'feature' is too specific, I agree with you.

> So in my humble opinion, version was the correct location, it
> is just a confusing name. (i.e. you can have many *versions*
> of an EIP197B, for instance ...)

That would be an issue with the driver. We named the 'version' given the
knowledge we had of the h/w, it might not be specific enough. Or maybe
you can think of this as being a "family of engine versions". The idea
is the version is what the h/w is capable of, not how it's being
wired/accessed.

> > > +		/*
> > > +		 * Request MSI vectors for global + 1 per ring -
> > > +		 * or just 1 for older dev images
> > > +		 */
> > > +		struct pci_dev *pci_pdev = pdev;
> > > +
> > > +		ret = pci_alloc_irq_vectors(pci_pdev,
> > > +					    priv->config.rings + 1,
> > > +					    priv->config.rings + 1,
> > > +					    PCI_IRQ_MSI|PCI_IRQ_MSIX);
> > 
> > You need a space before and after the | here.
> > 
> Ok, will add (checkpatch did not complain though)

It may complain with --strict on this one. (Well, I'm sure many --strict
tests won't pass on the existing upstream code, no worries :)).

> > > +		if (ret < 0) {
> > > +			dev_err(dev, "Failed to allocate PCI MSI interrupts");
> > 
> > Do not forget the \n at the end of the string.
> > 
> Actually, I removed all "\n"'s from my messages as I 
> understood they are not needed? If they are really needed,
> I can add them to all log strings again ... anyone else?

The simple answer is: everybody set the \n, so at least for consistency
we should have them.

> > > @@ -1189,13 +1249,12 @@ static int safexcel_remove(struct platform_device *pdev)
> > >  		.compatible = "inside-secure,safexcel-eip197d",
> > >  		.data = (void *)EIP197D,
> > >  	},
> > > +	/* For backward compatibiliry and intended for generic use */
> > >  	{
> > > -		/* Deprecated. Kept for backward compatibility. */
> > >  		.compatible = "inside-secure,safexcel-eip97",
> > >  		.data = (void *)EIP97IES,
> > >  	},
> > >  	{
> > > -		/* Deprecated. Kept for backward compatibility. */
> > >  		.compatible = "inside-secure,safexcel-eip197",
> > >  		.data = (void *)EIP197B,
> > >  	},
> > 
> > I'm not sure about this. The compatible should describe what the
> > hardware is, and the driver can then decide if it has special things to
> > do or not. It is not used to configure the driver to be used with a
> > generic use or not.
> > 
> > Do you have a practical reason to do this?
> 	
> I have to admit I don't fully understand how these compatible
> strings work. All I wanted to achieve is provide some generic
> device tree entry to point to this driver, to be used for 
> devices other than Marvell. No need to convey b/d that way
> (or even eip97/197, for that matter) as that can all be probed.

Compatibles are used in device trees, which intend to be a description
of the hardware (not the configuration of how the hardware should be
used). So we can't have a compatible being a restricted configuration
use of a given hardware. But I think here you're right, and there is
room for a more generic eip197 compatible: the b/d versions only have
few differences and are part of the same family, so we can have a very
specific compatible plus a "family" one. Something like:

  compatible = "inside-secure,safexcel-eip197d", "inside-secure,safexcel-eip197";

This would need to be in a separated patch, and this should be
documented in:
Documentation/devicetree/bindings/crypto/inside-secure-safexcel.txt

> > > +		/* enable the device */
> > > +		rc = pcim_enable_device(pdev);
> > > +		if (rc) {
> > > +			dev_err(dev, "pci_enable_device() failed");
> > 
> > Please use error messages describing the issue rather than printing the
> > function names. (There are other examples).
> > 
> But ... that IS the issue, isn't it? Well, apart from the actual
> return code. What message text would you suggest?

Yes, it is the issue. We generally use a sentence instead of function
names (something alongside s/_/ / :)).

> > > +			/* HW reset FPGA dev board */
> > > +			// assert reset
> > > +			writel(1, priv->base + XILINX_GPIO_BASE);
> > > +			wmb(); /* maintain strict ordering for accesses here */
> > > +			// deassert reset
> > > +			writel(0, priv->base + XILINX_GPIO_BASE);
> > > +			wmb(); /* maintain strict ordering for accesses here */
> > 
> > It seems the driver here access to a GPIO controller, to assert and
> > de-assert reset, which is outside the crypto engine i/o range. If true,
> > this is not acceptable in the upstream kernel: those GPIO or reset
> > should be accessed through the dedicated in-kernel API and be
> > implemented in separate drivers (maybe a reset driver here).
> > 
> Hmmm ... this is some *local* GPIO controller *inside*
> the FPGA device (i.e. doesn't even leave the silicon die).
> It's inside the range of the (single!) PCIE device, it's not
> a seperate device and thus cannot be managed as such ...
> 
> Effectively, it's just an MMIO mapped register no different
> from any other slave accessible register.
> If I had given it a less explicit name, nobody would've cared.

OK, that makes sense. If the register accessed is within the register
bank of the crypto engine you can keep this.

> > > +static struct pci_driver crypto_is_pci_driver = {
> > > +	.name          = "crypto-safexcel",
> > > +	.id_table      = crypto_is_pci_ids,
> > > +	.probe         = crypto_is_pci_probe,
> > > +	.remove        = crypto_is_pci_remove,
> > > +};
> > 
> > More generally, you should protect all the PCI specific functions and
> > definitions between #ifdef.
> > 
> I asked the mailing list and the answer was I should NOT use #ifdef,
> but instead use IS_ENABLED to *only* remove relevant function bodies.
> Which is exactly what I did (or tried to do, anyway).

My bad, I realise there's a mistake in my comment. That should have
been: you should protect all the PCI specific functions and definitions
with #if IS_ENABLED(...). When part of a function should be excluded
you can use if(IS_ENABLED(...)), but if the entire function can be left
out, #if is the way to go.

Thanks!
Antoine

-- 
Antoine Ténart, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* [LTP] [PATCH] pkey: Add test for memory protection keys
From: Jan Stancek @ 2019-06-20 13:05 UTC (permalink / raw)
  To: ltp
In-Reply-To: <20190620095548.28335-1-liwang@redhat.com>



----- Original Message -----
> Signed-off-by: Li Wang <liwang@redhat.com>
> ---
>  configure.ac                               |   1 +
>  include/lapi/syscalls/aarch64.in           |   3 +
>  include/lapi/syscalls/arm.in               |   3 +
>  include/lapi/syscalls/i386.in              |   3 +
>  include/lapi/syscalls/ia64.in              |   3 +
>  include/lapi/syscalls/powerpc.in           |   3 +
>  include/lapi/syscalls/powerpc64.in         |   3 +
>  include/lapi/syscalls/s390.in              |   3 +
>  include/lapi/syscalls/s390x.in             |   3 +
>  include/lapi/syscalls/sh.in                |   3 +
>  include/lapi/syscalls/sparc.in             |   3 +
>  include/lapi/syscalls/sparc64.in           |   3 +
>  include/lapi/syscalls/x86_64.in            |   3 +
>  runtest/syscalls                           |   2 +
>  testcases/kernel/syscalls/pkeys/.gitignore |   1 +
>  testcases/kernel/syscalls/pkeys/Makefile   |   8 ++
>  testcases/kernel/syscalls/pkeys/pkey.h     |  44 +++++++++
>  testcases/kernel/syscalls/pkeys/pkey01.c   | 105 +++++++++++++++++++++
>  18 files changed, 197 insertions(+)
>  create mode 100644 testcases/kernel/syscalls/pkeys/.gitignore
>  create mode 100644 testcases/kernel/syscalls/pkeys/Makefile
>  create mode 100644 testcases/kernel/syscalls/pkeys/pkey.h
>  create mode 100644 testcases/kernel/syscalls/pkeys/pkey01.c
> 
> diff --git a/configure.ac b/configure.ac
> index 5ecc92781..35997699f 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -76,6 +76,7 @@ AC_CHECK_FUNCS([ \
>      profil \
>      pwritev \
>      pwritev2 \
> +    pkey_mprotect \
>      readlinkat \
>      renameat \
>      renameat2 \
> diff --git a/include/lapi/syscalls/aarch64.in
> b/include/lapi/syscalls/aarch64.in
> index 177dd0115..4232defbe 100644
> --- a/include/lapi/syscalls/aarch64.in
> +++ b/include/lapi/syscalls/aarch64.in
> @@ -266,3 +266,6 @@ copy_file_range 285
>  preadv2 286
>  pwritev2 287
>  _sysctl 1078
> +pkey_mprotect 394
> +pkey_alloc 395
> +pkey_free 396

288, 289, 290

> diff --git a/include/lapi/syscalls/arm.in b/include/lapi/syscalls/arm.in
> index f4adedb2c..48b55b5ff 100644
> --- a/include/lapi/syscalls/arm.in
> +++ b/include/lapi/syscalls/arm.in
> @@ -350,3 +350,6 @@ copy_file_range (__NR_SYSCALL_BASE+391)
>  preadv2 (__NR_SYSCALL_BASE+392)
>  pwritev2 (__NR_SYSCALL_BASE+393)
>  statx (__NR_SYSCALL_BASE+397)
> +pkey_mprotect (__NR_SYSCALL_BASE+394)
> +pkey_alloc (__NR_SYSCALL_BASE+395)
> +pkey_free (__NR_SYSCALL_BASE+396)
> diff --git a/include/lapi/syscalls/i386.in b/include/lapi/syscalls/i386.in
> index af5254f77..c54573547 100644
> --- a/include/lapi/syscalls/i386.in
> +++ b/include/lapi/syscalls/i386.in
> @@ -348,3 +348,6 @@ copy_file_range 377
>  preadv2 378
>  pwritev2 379
>  statx 383
> +pkey_mprotect 380
> +pkey_alloc 381
> +pkey_free 382
> diff --git a/include/lapi/syscalls/ia64.in b/include/lapi/syscalls/ia64.in
> index c0aeed08b..56bfd7928 100644
> --- a/include/lapi/syscalls/ia64.in
> +++ b/include/lapi/syscalls/ia64.in
> @@ -305,3 +305,6 @@ mlock2 1346
>  copy_file_range 1347
>  preadv2 1348
>  pwritev2 1349
> +pkey_mprotect 330
> +pkey_alloc 331
> +pkey_free 332
> diff --git a/include/lapi/syscalls/powerpc.in
> b/include/lapi/syscalls/powerpc.in
> index 6b6be58a7..eaf8d45ed 100644
> --- a/include/lapi/syscalls/powerpc.in
> +++ b/include/lapi/syscalls/powerpc.in
> @@ -355,3 +355,6 @@ copy_file_range 379
>  preadv2 380
>  pwritev2 381
>  statx 383
> +pkey_mprotect 386
> +pkey_alloc 384
> +pkey_free 385
> diff --git a/include/lapi/syscalls/powerpc64.in
> b/include/lapi/syscalls/powerpc64.in
> index 6b6be58a7..eaf8d45ed 100644
> --- a/include/lapi/syscalls/powerpc64.in
> +++ b/include/lapi/syscalls/powerpc64.in
> @@ -355,3 +355,6 @@ copy_file_range 379
>  preadv2 380
>  pwritev2 381
>  statx 383
> +pkey_mprotect 386
> +pkey_alloc 384
> +pkey_free 385
> diff --git a/include/lapi/syscalls/s390.in b/include/lapi/syscalls/s390.in
> index 2a2ffe223..3ee5547f1 100644
> --- a/include/lapi/syscalls/s390.in
> +++ b/include/lapi/syscalls/s390.in
> @@ -338,3 +338,6 @@ mlock2 374
>  copy_file_range 375
>  preadv2 376
>  pwritev2 377
> +pkey_mprotect 384
> +pkey_alloc 385
> +pkey_free 386
> diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
> index 4c36ce17c..92e882aae 100644
> --- a/include/lapi/syscalls/s390x.in
> +++ b/include/lapi/syscalls/s390x.in
> @@ -337,3 +337,6 @@ mlock2 374
>  copy_file_range 375
>  preadv2 376
>  pwritev2 377
> +pkey_mprotect 384
> +pkey_alloc 385
> +pkey_free 386
> diff --git a/include/lapi/syscalls/sh.in b/include/lapi/syscalls/sh.in
> index a942fb506..00726c1cc 100644
> --- a/include/lapi/syscalls/sh.in
> +++ b/include/lapi/syscalls/sh.in
> @@ -369,3 +369,6 @@ mlock2 390
>  copy_file_range 391
>  preadv2 392
>  pwritev2 393
> +pkey_mprotect 384
> +pkey_alloc 385
> +pkey_free 386
> diff --git a/include/lapi/syscalls/sparc.in b/include/lapi/syscalls/sparc.in
> index 20dc37b01..1b34ab489 100644
> --- a/include/lapi/syscalls/sparc.in
> +++ b/include/lapi/syscalls/sparc.in
> @@ -343,3 +343,6 @@ mlock2 356
>  copy_file_range 357
>  preadv2 358
>  pwritev2 359
> +pkey_mprotect 362
> +pkey_alloc 363
> +pkey_free 364
> diff --git a/include/lapi/syscalls/sparc64.in
> b/include/lapi/syscalls/sparc64.in
> index c100b8e3e..f3142fbdd 100644
> --- a/include/lapi/syscalls/sparc64.in
> +++ b/include/lapi/syscalls/sparc64.in
> @@ -319,3 +319,6 @@ mlock2 356
>  copy_file_range 357
>  preadv2 358
>  pwritev2 359
> +pkey_mprotect 362
> +pkey_alloc 363
> +pkey_free 364
> diff --git a/include/lapi/syscalls/x86_64.in
> b/include/lapi/syscalls/x86_64.in
> index 87849e5c0..9c77f1c67 100644
> --- a/include/lapi/syscalls/x86_64.in
> +++ b/include/lapi/syscalls/x86_64.in
> @@ -315,3 +315,6 @@ copy_file_range 326
>  preadv2 327
>  pwritev2 328
>  statx 332
> +pkey_mprotect 329
> +pkey_alloc 330
> +pkey_free 331
> diff --git a/runtest/syscalls b/runtest/syscalls
> index a1106fb84..a236fce09 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -723,6 +723,8 @@ mprotect02 mprotect02
>  mprotect03 mprotect03
>  mprotect04 mprotect04
>  
> +pkey01 pkey01
> +
>  mq_notify01 mq_notify01
>  mq_notify02 mq_notify02
>  mq_open01 mq_open01
> diff --git a/testcases/kernel/syscalls/pkeys/.gitignore
> b/testcases/kernel/syscalls/pkeys/.gitignore
> new file mode 100644
> index 000000000..6fd5addb8
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/.gitignore
> @@ -0,0 +1 @@
> +/pkey01
> diff --git a/testcases/kernel/syscalls/pkeys/Makefile
> b/testcases/kernel/syscalls/pkeys/Makefile
> new file mode 100644
> index 000000000..9ee2c2ea5
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2019 Red Hat, Inc.
> +
> +top_srcdir		?= ../../../..
> +
> +include $(top_srcdir)/include/mk/testcases.mk
> +
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/pkeys/pkey.h
> b/testcases/kernel/syscalls/pkeys/pkey.h
> new file mode 100644
> index 000000000..bd86bebcc
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/pkey.h
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Red Hat, Inc.
> + */
> +
> +#ifndef PKEYS_H
> +#define PKEYS_H
> +
> +#include "tst_test.h"
> +#include "lapi/syscalls.h"
> +
> +#ifndef PKEY_DISABLE_ACCESS
> +# define PKEY_DISABLE_ACCESS 0x1
> +# define PKEY_DISABLE_WRITE  0x2
> +#endif
> +
> +#ifndef HAVE_PKEY_MPROTECT
> +static inline int pkey_mprotect(void *addr, size_t len, int prot, int pkey)
> +{
> +	return tst_syscall(SYS_pkey_mprotect, addr, len, prot, pkey);
> +}
> +
> +static inline int pkey_alloc(unsigned int flags, unsigned int access_rights)
> +{
> +	return tst_syscall(SYS_pkey_alloc, flags, access_rights);
> +}
> +
> +static inline int pkey_free(int pkey)
> +{
> +	return tst_syscall(SYS_pkey_free, pkey);
> +}
> +#endif /* HAVE_PKEY_MPROTECT */
> +
> +static inline void check_pkey_support(void)
> +{
> +	int pkey = pkey_alloc(0, 0);
> +
> +	if ((pkey == -1) && (errno == EINVAL))

Shouldn't this handle also ENOSPC?

      ENOSPC (pkey_alloc()) All protection keys available for the current process have been allocated.  The number of keys available is
              architecture-specific  and  implementation-specific  and may be reduced by kernel-internal use of certain keys.  There are
              currently 15 keys available to user programs on x86.

              This error will also be returned if the processor or operating system does  not  support  protection  keys.   Applications
              should  always  be prepared to handle this error, since factors outside of the application's control can reduce the number
              of available pkeys.

> +		tst_brk(TCONF, "pkey_alloc is not supported");
> +	else
> +		pkey_free(pkey);
> +}
> +
> +#endif /* PKEYS_H */
> diff --git a/testcases/kernel/syscalls/pkeys/pkey01.c
> b/testcases/kernel/syscalls/pkeys/pkey01.c
> new file mode 100644
> index 000000000..8faa4be4c
> --- /dev/null
> +++ b/testcases/kernel/syscalls/pkeys/pkey01.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2019 Red Hat, Inc.
> + *
> + * Test for Memory Protection Keys
> + * Reference: https://lwn.net/Articles/689395/
> + */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <sys/syscall.h>
> +#include <sys/mman.h>
> +#include <sys/wait.h>
> +
> +#include "pkey.h"
> +
> +static int psize;
> +static char *buffer;
> +
> +static struct tcase {
> +	unsigned long flags;
> +	unsigned long access_rights;
> +	char *name;
> +} tcases[] = {
> +	{0, PKEY_DISABLE_ACCESS, "PKEY_DISABLE_ACCESS"},
> +	{0, PKEY_DISABLE_WRITE, "PKEY_DISABLE_WRITE"},
> +};
> +
> +static void setup(void)
> +{
> +	check_pkey_support();
> +
> +	psize = getpagesize();
> +	buffer = SAFE_MMAP(NULL, psize, PROT_READ | PROT_WRITE,
> +			MAP_ANONYMOUS | MAP_SHARED, -1, 0);
> +	memset(buffer, 'a', psize);
> +}
> +
> +static void verify_pkey(unsigned int i)
> +{
> +	int pkey, status;
> +	pid_t pid;
> +
> +	struct tcase *tc = &tcases[i];
> +
> +	pkey = pkey_alloc(tc->flags, tc->access_rights);
> +	if (pkey == -1)
> +		tst_brk(TBROK, "pkey_alloc failed");
> +
> +	tst_res(TINFO, "Set %s on buffer", tc->name);
> +	if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, pkey) == -1)
> +		tst_brk(TBROK, "pkey_mprotect failed");
> +
> +	pid = SAFE_FORK();
> +	if (pid == 0) {

I'd suggest something like:
                struct rlimit r;                                                                                                            
                                                                                                                                            
                r.rlim_cur = 1;                                                                                                             
                r.rlim_max = 1;                                                                                                             
                SAFE_SETRLIMIT(RLIMIT_CORE, &r); 

to avoid getting cores from this child - since it is expected to segfault.

> +		switch (tc->access_rights) {
> +		case PKEY_DISABLE_ACCESS:
> +			tst_res(TFAIL, "Read buffer success, buffer[0] = %d", *buffer);
> +		break;
> +		case PKEY_DISABLE_WRITE:
> +			*buffer = 'b';
> +		break;
> +		}
> +		exit(0);
> +	}
> +
> +	SAFE_WAITPID(pid, &status, 0);
> +	if (WIFSIGNALED(status)) {
> +		if (WTERMSIG(status) == SIGSEGV) {
> +			tst_res(TPASS, "Child ended by %s as expected",
> +				tst_strsig(SIGSEGV));
> +		} else {
> +			tst_res(TFAIL, "Child ended by %s unexpected" ,
> +				tst_strsig(WTERMSIG(status)));
> +		}
> +	} else {
> +		tst_res(TFAIL, "Child unexpectedly ended");
> +	}
> +
> +	tst_res(TINFO, "Remove %s from buffer", tc->name);
> +	if (pkey_mprotect(buffer, psize, PROT_READ | PROT_WRITE, 0x0) == -1)
> +		tst_brk(TBROK, "pkey_mprotect failed");
> +	*buffer = i;
> +	tst_res(TPASS, "Write buffer success, buffer[0] = %d", *buffer);
> +
> +	if (pkey_free(pkey) == -1)
> +		tst_brk(TBROK, "pkey_free failed");
> +}
> +
> +static void cleanup(void)
> +{
> +	if (buffer)
> +		SAFE_MUNMAP(buffer, psize);
> +}
> +
> +static struct tst_test test = {
> +	.tcnt = ARRAY_SIZE(tcases),
> +	.forks_child = 1,
> +	.test = verify_pkey,
> +	.setup = setup,
> +	.cleanup = cleanup,
> +};
> --
> 2.20.1
> 
> 
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
> 

^ permalink raw reply

* Re: [RFC PATCH 1/7] PM: Introduce em_pd_get_higher_freq()
From: Patrick Bellasi @ 2019-06-20 13:04 UTC (permalink / raw)
  To: Douglas Raillard
  Cc: Quentin Perret, linux-kernel, linux-pm, mingo, peterz,
	dietmar.eggemann
In-Reply-To: <11976c37-65d3-e0c6-034d-cfec9ebb5b49@arm.com>

On 19-Jun 17:08, Douglas Raillard wrote:
> Hi Patrick,
> 
> On 5/16/19 2:22 PM, Patrick Bellasi wrote:
> > On 16-May 14:01, Quentin Perret wrote:
> > > On Thursday 16 May 2019 at 13:42:00 (+0100), Patrick Bellasi wrote:
> > > > > +static inline unsigned long em_pd_get_higher_freq(struct em_perf_domain *pd,
> > > > > +	unsigned long min_freq, unsigned long cost_margin)
> > > > > +{
> > > > > +	unsigned long max_cost = 0;
> > > > > +	struct em_cap_state *cs;
> > > > > +	int i;
> > > > > +
> > > > > +	if (!pd)
> > > > > +		return min_freq;
> > > > > +
> > > > > +	/* Compute the maximum allowed cost */
> > > > > +	for (i = 0; i < pd->nr_cap_states; i++) {
> > > > > +		cs = &pd->table[i];
> > > > > +		if (cs->frequency >= min_freq) {
> > > > > +			max_cost = cs->cost + (cs->cost * cost_margin) / 1024;
> > > >                                                                           ^^^^
> > > > ... end here we should probably better use SCHED_CAPACITY_SCALE
> > > > instead of hard-coding in values, isn't it?
> > > 
> > > I'm not sure to agree. This isn't part of the scheduler per se, and the
> > > cost thing isn't in units of capacity, but in units of power, so I don't
> > > think SCHED_CAPACITY_SCALE is correct here.
> > 
> > Right, I get the units do not match and it would not be elegant to use
> > it here...
> > 
> > > But I agree these hard coded values (that one, and the 512 in one of the
> > > following patches) could use some motivation :-)
> > 
> > ... ultimately SCHED_CAPACITY_SCALE is just SCHED_FIXEDPOINT_SCALE,
> > which is adimensional. Perhaps we should use that or yet another alias
> > for the same.
> 
> Would it be a good idea to use SCHED_FIXEDPOINT_SCALE in energy.c ?
> Since it's not part of the scheduler, maybe there is a scale covering a wider scope,
> or we can introduce a similar ENERGY_FIXEDPOINT_SCALE in energy_model.h.

Well, in energy_model.c we have references to "capacity" and
"utilization" which are all SCHED_FIXEDPOINT_SCALE range values.
That symbol is defined in <linux/sched.h> and we already pull
in other <linux/sched/*> headers.

So, to me it seems it's not unreasonable to say that we use scheduler
related concepts and it makes more sense than introducing yet another
scaling factor.

But that's just my two cents ;)

Best,
Patrick

-- 
#include <best/regards.h>

Patrick Bellasi

^ permalink raw reply

* Re: [PATCH v2 net-next 0/2] net: mediatek: Add MT7621 TRGMII mode support
From: Frank Wunderlich @ 2019-06-20 13:02 UTC (permalink / raw)
  To: René van Dorst, sean.wang, f.fainelli, davem, matthias.bgg,
	andrew, vivien.didelot
  Cc: netdev, john, linux-mediatek, linux-mips
In-Reply-To: <20190620122155.32078-1-opensource@vdorst.com>

Tested on Bananapi R2 (mt7623)

Tested-by: "Frank Wunderlich" <frank-w@public-files.de>

Am 20. Juni 2019 14:21:53 MESZ schrieb "René van Dorst" <opensource@vdorst.com>:
>Like many other mediatek SOCs, the MT7621 SOC and the internal MT7530
>switch both supports TRGMII mode. MT7621 TRGMII speed is fix 1200MBit.
>
>v1->v2: 
> - Fix breakage on non MT7621 SOC
> - Support 25MHz and 40MHz XTAL as MT7530 clocksource
>
>René van Dorst (2):
>  net: ethernet: mediatek: Add MT7621 TRGMII mode support
>  net: dsa: mt7530: Add MT7621 TRGMII mode support
>
> drivers/net/dsa/mt7530.c                    | 46 ++++++++++++++++-----
> drivers/net/dsa/mt7530.h                    |  4 ++
> drivers/net/ethernet/mediatek/mtk_eth_soc.c | 38 +++++++++++++++--
> drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 +++++
> 4 files changed, 85 insertions(+), 14 deletions(-)

^ permalink raw reply

* Re: [PATCH v3 1/6] crypto: essiv - create wrapper template for ESSIV generation
From: Ard Biesheuvel @ 2019-06-20 13:02 UTC (permalink / raw)
  To: Herbert Xu
  Cc: Eric Biggers, open list:HARDWARE RANDOM NUMBER GENERATOR CORE,
	device-mapper development, linux-fscrypt, Gilad Ben-Yossef,
	Milan Broz
In-Reply-To: <20190620125339.gqup5623sw4xrsmi@gondor.apana.org.au>

On Thu, 20 Jun 2019 at 14:53, Herbert Xu <herbert@gondor.apana.org.au> wrote:
>
> On Thu, Jun 20, 2019 at 09:30:41AM +0200, Ard Biesheuvel wrote:
> >
> > Is this the right approach? Or are there better ways to convey this
> > information when instantiating the template?
> > Also, it seems to me that the dm-crypt and fscrypt layers would
> > require major surgery in order to take advantage of this.
>
> Oh and you don't have to make dm-crypt use it from the start.  That
> is, you can just make things simple by doing it one sector at a
> time in the dm-crypt code even though the underlying essiv code
> supports multiple sectors.
>
> Someone who cares about this is sure to come along and fix it later.
>

It also depend on how realistic it is that we will need to support
arbitrary sector sizes in the future. I mean, if we decide today that
essiv() uses an implicit sector size of 4k, we can always add
essiv64k() later, rather than adding lots of complexity now that we
are never going to use. Note that ESSIV is already more or less
deprecated, so there is really no point in inventing these weird and
wonderful things if we want people to move to XTS and plain IV
generation instead.

^ permalink raw reply

* Re: [PATCH] drm/i915/execlists: Preempt-to-busy
From: Chris Wilson @ 2019-06-20 13:01 UTC (permalink / raw)
  To: Mika Kuoppala, intel-gfx
In-Reply-To: <874l4k77k9.fsf@gaia.fi.intel.com>

Quoting Mika Kuoppala (2019-06-20 13:41:26)
> Chris Wilson <chris@chris-wilson.co.uk> writes:
> > @@ -38,6 +39,10 @@ struct intel_context {
> >       struct i915_gem_context *gem_context;
> >       struct intel_engine_cs *engine;
> >       struct intel_engine_cs *inflight;
> > +#define intel_context_inflight(ce) ptr_mask_bits((ce)->inflight, 2)
> > +#define intel_context_inflight_count(ce)  ptr_unmask_bits((ce)->inflight, 2)
> > +#define intel_context_inflight_inc(ce) ptr_count_inc(&(ce)->inflight)
> > +#define intel_context_inflight_dec(ce) ptr_count_dec(&(ce)->inflight)
> 
> Just curious here that what you consider the advantages of carrying
> this info with the pointer?

Packing. I just need a bit to track status, and one for overflow.

> > +static inline u32 intel_hws_preempt_address(struct intel_engine_cs *engine)
> > +{
> > +     return (i915_ggtt_offset(engine->status_page.vma) +
> > +             I915_GEM_HWS_PREEMPT_ADDR);
> > +}
> > +
> > +#define ring_pause(E) ((E)->status_page.addr[I915_GEM_HWS_PREEMPT])
> 
> Scary. Please lets make a function of ring_pause and use
> intel_write_status_page in it.

I'd rather not unless you do __intel_write_state_page.

> So I guess you have and you want squeeze the latency fruit.
> 
> When we have everything in place, CI is green and
> everyone is happy, then we tear it down?

Been there, done that.

> > @@ -442,13 +443,11 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
> >               struct intel_engine_cs *owner;
> >  
> >               if (i915_request_completed(rq))
> > -                     break;
> > +                     continue; /* XXX */
> 
> Yeah, but what is the plan with the XXX.

Mulling over tracking context not requests. We still end up with having
to scan history within a context, so not yet seeing anything to
encourage me to make the change. I worry about long request queues
causing preemption latency, as this list is currently only trimmed in
retirement.

One idea in the background is for a scheduler (contemplating something
like the isosynchronous MuQSS) and that might call for a change to
using contexts as the primary, with requests within the contexts.

> > @@ -1223,68 +1217,37 @@ static void process_csb(struct intel_engine_cs *engine)
> >                * status notifier.
> >                */
> >  
> > -             GEM_TRACE("%s csb[%d]: status=0x%08x:0x%08x, active=0x%x\n",
> > +             GEM_TRACE("%s csb[%d]: status=0x%08x:0x%08x\n",
> >                         engine->name, head,
> > -                       buf[2 * head + 0], buf[2 * head + 1],
> > -                       execlists->active);
> > +                       buf[2 * head + 0], buf[2 * head + 1]);
> >  
> >               status = buf[2 * head];
> > -             if (status & (GEN8_CTX_STATUS_IDLE_ACTIVE |
> > -                           GEN8_CTX_STATUS_PREEMPTED))
> > -                     execlists_set_active(execlists,
> > -                                          EXECLISTS_ACTIVE_HWACK);
> > -             if (status & GEN8_CTX_STATUS_ACTIVE_IDLE)
> > -                     execlists_clear_active(execlists,
> > -                                            EXECLISTS_ACTIVE_HWACK);
> > -
> > -             if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK))
> > -                     continue;
> > +             if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) {
> > +promote:
> > +                     GEM_BUG_ON(!assert_pending_valid(execlists, "promote"));
> > +                     execlists->active =
> > +                             memcpy(execlists->inflight,
> > +                                    execlists->pending,
> > +                                    execlists_num_ports(execlists) *
> > +                                    sizeof(*execlists->pending));
> > +                     execlists->pending[0] = NULL;
> 
> I can't decide if comment or a helper inline function would
> serve better as documentation of between inflight and pending
> movement.

The magic is just this function, I think process_csb() reads quite
nicely with the 3 branches and switching between different states. It's
about 8 lines without the comments and asserts.

> I guess it is better to be left as a future work after
> the dust settles.
> 
> Just general yearning for a similar kind of level of documentation
> steps as in dequeue.
> 
> >  
> > -             /* We should never get a COMPLETED | IDLE_ACTIVE! */
> > -             GEM_BUG_ON(status & GEN8_CTX_STATUS_IDLE_ACTIVE);
> 
> Is our assert coverage going to suffer?

You've looked at the added asserts and tracing; I claim we get stronger.

> > @@ -2514,15 +2452,29 @@ static u32 *gen8_emit_wa_tail(struct i915_request *request, u32 *cs)
> >       return cs;
> >  }
> >  
> > +static u32 *emit_preempt_busywait(struct i915_request *request, u32 *cs)
> > +{
> > +     *cs++ = MI_SEMAPHORE_WAIT |
> > +             MI_SEMAPHORE_GLOBAL_GTT |
> > +             MI_SEMAPHORE_POLL |
> > +             MI_SEMAPHORE_SAD_EQ_SDD;
> > +     *cs++ = 0;
> > +     *cs++ = intel_hws_preempt_address(request->engine);
> > +     *cs++ = 0;
> > +
> > +     return cs;
> > +}
> > +
> >  static u32 *gen8_emit_fini_breadcrumb(struct i915_request *request, u32 *cs)
> >  {
> >       cs = gen8_emit_ggtt_write(cs,
> >                                 request->fence.seqno,
> >                                 request->timeline->hwsp_offset,
> >                                 0);
> > -
> >       *cs++ = MI_USER_INTERRUPT;
> > +
> >       *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
> 
> This was discussed in irc, could warrant a comment here of
> why this is needed. Precious info.

Why the ARB, for reasons of yore. The comment for why we need it is
actually in bb_start.

commit 279f5a00c9a9b39f4f6e9813e6d4da8c181d34c8
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Oct 5 20:10:05 2017 +0100

    drm/i915/execlists: Add a comment for the extra MI_ARB_ENABLE


> > +     cs = emit_preempt_busywait(request, cs);

Why we use the semaphore? That should be explained in dequeue upon
setting up the preemption.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: [PATCH v3 1/6] crypto: essiv - create wrapper template for ESSIV generation
From: Ard Biesheuvel @ 2019-06-20 13:02 UTC (permalink / raw)
  To: Herbert Xu
  Cc: linux-fscrypt, Eric Biggers, Gilad Ben-Yossef,
	device-mapper development,
	open list:HARDWARE RANDOM NUMBER GENERATOR CORE, Milan Broz
In-Reply-To: <20190620125339.gqup5623sw4xrsmi@gondor.apana.org.au>

On Thu, 20 Jun 2019 at 14:53, Herbert Xu <herbert@gondor.apana.org.au> wrote:
>
> On Thu, Jun 20, 2019 at 09:30:41AM +0200, Ard Biesheuvel wrote:
> >
> > Is this the right approach? Or are there better ways to convey this
> > information when instantiating the template?
> > Also, it seems to me that the dm-crypt and fscrypt layers would
> > require major surgery in order to take advantage of this.
>
> Oh and you don't have to make dm-crypt use it from the start.  That
> is, you can just make things simple by doing it one sector at a
> time in the dm-crypt code even though the underlying essiv code
> supports multiple sectors.
>
> Someone who cares about this is sure to come along and fix it later.
>

It also depend on how realistic it is that we will need to support
arbitrary sector sizes in the future. I mean, if we decide today that
essiv() uses an implicit sector size of 4k, we can always add
essiv64k() later, rather than adding lots of complexity now that we
are never going to use. Note that ESSIV is already more or less
deprecated, so there is really no point in inventing these weird and
wonderful things if we want people to move to XTS and plain IV
generation instead.

^ permalink raw reply

* [PATCH] Add SPDX identifiers
From: yegorslists @ 2019-06-20 13:01 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Yegor Yefremov

From: Yegor Yefremov <yegorslists@googlemail.com>

Software Package Data Exchange identifiers help to detect source file
licenses and hence simplify the FOSS compliance process.

Signed-off-by: Yegor Yefremov <yegorslists@googlemail.com>
---
 ap.c           | 2 ++
 bitrate.c      | 2 ++
 bloom.c        | 2 ++
 coalesce.c     | 2 ++
 connect.c      | 2 ++
 cqm.c          | 2 ++
 event.c        | 2 ++
 ftm.c          | 2 ++
 genl.c         | 2 ++
 hwsim.c        | 2 ++
 ibss.c         | 2 ++
 ieee80211.h    | 2 ++
 info.c         | 2 ++
 interface.c    | 2 ++
 iw.c           | 2 ++
 iw.h           | 2 ++
 link.c         | 2 ++
 measurements.c | 2 ++
 mesh.c         | 2 ++
 mgmt.c         | 2 ++
 mpath.c        | 2 ++
 mpp.c          | 2 ++
 nan.c          | 2 ++
 nl80211.h      | 2 ++
 ocb.c          | 2 ++
 offch.c        | 2 ++
 p2p.c          | 2 ++
 phy.c          | 2 ++
 ps.c           | 2 ++
 reason.c       | 2 ++
 reg.c          | 2 ++
 roc.c          | 2 ++
 scan.c         | 2 ++
 sections.c     | 2 ++
 sha256.c       | 2 ++
 sha256.h       | 2 ++
 station.c      | 2 ++
 status.c       | 2 ++
 survey.c       | 2 ++
 util.c         | 2 ++
 vendor.c       | 2 ++
 wowlan.c       | 2 ++
 42 files changed, 84 insertions(+)

diff --git a/ap.c b/ap.c
index db9efb7..4b9157a 100644
--- a/ap.c
+++ b/ap.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
diff --git a/bitrate.c b/bitrate.c
index 4a026a4..c0ff319 100644
--- a/bitrate.c
+++ b/bitrate.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 
 #include "nl80211.h"
diff --git a/bloom.c b/bloom.c
index 877a6b5..f697b94 100644
--- a/bloom.c
+++ b/bloom.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <inttypes.h>
 #include "iw.h"
 
diff --git a/coalesce.c b/coalesce.c
index 36dcaef..f3826ca 100644
--- a/coalesce.c
+++ b/coalesce.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
diff --git a/connect.c b/connect.c
index 3237a27..a486d21 100644
--- a/connect.c
+++ b/connect.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 
 #include <netlink/genl/genl.h>
diff --git a/cqm.c b/cqm.c
index 093b744..4e2e846 100644
--- a/cqm.c
+++ b/cqm.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 
 #include <netlink/genl/genl.h>
diff --git a/event.c b/event.c
index 100f644..a8b4611 100644
--- a/event.c
+++ b/event.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <stdint.h>
 #include <stdbool.h>
 #include <net/if.h>
diff --git a/ftm.c b/ftm.c
index 23be38e..03eaf38 100644
--- a/ftm.c
+++ b/ftm.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 
 #include <netlink/genl/genl.h>
diff --git a/genl.c b/genl.c
index 7dc27f7..f8dbac3 100644
--- a/genl.c
+++ b/genl.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 /*
  * This ought to be provided by libnl
  */
diff --git a/hwsim.c b/hwsim.c
index 6f82207..fbfaed3 100644
--- a/hwsim.c
+++ b/hwsim.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 
diff --git a/ibss.c b/ibss.c
index f6cbc4c..645639e 100644
--- a/ibss.c
+++ b/ibss.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 #include <strings.h>
diff --git a/ieee80211.h b/ieee80211.h
index 8745608..0a7e205 100644
--- a/ieee80211.h
+++ b/ieee80211.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #ifndef __IEEE80211
 #define __IEEE80211
 
diff --git a/info.c b/info.c
index e6270c8..fc0361d 100644
--- a/info.c
+++ b/info.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <stdbool.h>
 
 #include <netlink/genl/genl.h>
diff --git a/interface.c b/interface.c
index b697482..de5546b 100644
--- a/interface.c
+++ b/interface.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 #include <stdbool.h>
diff --git a/iw.c b/iw.c
index da71617..5bb22c4 100644
--- a/iw.c
+++ b/iw.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 /*
  * nl80211 userspace tool
  *
diff --git a/iw.h b/iw.h
index bc0b3ac..ea7bd6c 100644
--- a/iw.h
+++ b/iw.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #ifndef __IW_H
 #define __IW_H
 
diff --git a/link.c b/link.c
index 1ed7f63..4e73279 100644
--- a/link.c
+++ b/link.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 #include <errno.h>
 #include <string.h>
diff --git a/measurements.c b/measurements.c
index 385143f..54ca402 100644
--- a/measurements.c
+++ b/measurements.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 
 #include "nl80211.h"
diff --git a/mesh.c b/mesh.c
index 0650d0c..2591a4b 100644
--- a/mesh.c
+++ b/mesh.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 
diff --git a/mgmt.c b/mgmt.c
index 338435d..8639f9c 100644
--- a/mgmt.c
+++ b/mgmt.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <string.h>
 #include <errno.h>
 
diff --git a/mpath.c b/mpath.c
index e39c24b..3cb465b 100644
--- a/mpath.c
+++ b/mpath.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 #include <errno.h>
 #include <string.h>
diff --git a/mpp.c b/mpp.c
index 58bf28e..23193a4 100644
--- a/mpp.c
+++ b/mpp.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 #include <errno.h>
 
diff --git a/nan.c b/nan.c
index 1d8d795..a846b68 100644
--- a/nan.c
+++ b/nan.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 #include <errno.h>
 #include <string.h>
diff --git a/nl80211.h b/nl80211.h
index 6f09d15..750b116 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #ifndef __LINUX_NL80211_H
 #define __LINUX_NL80211_H
 /*
diff --git a/ocb.c b/ocb.c
index fc9579b..1678e49 100644
--- a/ocb.c
+++ b/ocb.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 
diff --git a/offch.c b/offch.c
index 19e170e..684eea3 100644
--- a/offch.c
+++ b/offch.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 
 #include <netlink/genl/genl.h>
diff --git a/p2p.c b/p2p.c
index 2d4bab0..1d12046 100644
--- a/p2p.c
+++ b/p2p.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
 #include <netlink/genl/ctrl.h>
diff --git a/phy.c b/phy.c
index 716677e..a5159c7 100644
--- a/phy.c
+++ b/phy.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <stdbool.h>
 #include <errno.h>
 #include <strings.h>
diff --git a/ps.c b/ps.c
index de36d2b..67f7a38 100644
--- a/ps.c
+++ b/ps.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 
diff --git a/reason.c b/reason.c
index f91c681..74f516b 100644
--- a/reason.c
+++ b/reason.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <stdint.h>
 #include "iw.h"
 
diff --git a/reg.c b/reg.c
index a2368df..7a83df2 100644
--- a/reg.c
+++ b/reg.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 #include <stdbool.h>
diff --git a/roc.c b/roc.c
index c6eda10..a159487 100644
--- a/roc.c
+++ b/roc.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 
diff --git a/scan.c b/scan.c
index 6ad3ad4..1993f0b 100644
--- a/scan.c
+++ b/scan.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 #include <errno.h>
 #include <string.h>
diff --git a/sections.c b/sections.c
index 38095f6..3b0ec8b 100644
--- a/sections.c
+++ b/sections.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include "iw.h"
 
 SECTION(get);
diff --git a/sha256.c b/sha256.c
index 4a43df8..da9d967 100644
--- a/sha256.c
+++ b/sha256.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include "sha256.h"
 
 /**
diff --git a/sha256.h b/sha256.h
index d3eb3c0..4a32604 100644
--- a/sha256.h
+++ b/sha256.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #ifndef SHA256
 #define SHA256
 
diff --git a/station.c b/station.c
index aaad079..d8f0ae3 100644
--- a/station.c
+++ b/station.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 #include <errno.h>
 #include <string.h>
diff --git a/status.c b/status.c
index 731727d..7529021 100644
--- a/status.c
+++ b/status.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <stdint.h>
 #include "iw.h"
 
diff --git a/survey.c b/survey.c
index 9325353..ffaf85a 100644
--- a/survey.c
+++ b/survey.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <net/if.h>
 
 #include <netlink/genl/genl.h>
diff --git a/util.c b/util.c
index 41277b5..55993c7 100644
--- a/util.c
+++ b/util.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <ctype.h>
 #include <netlink/attr.h>
 #include <errno.h>
diff --git a/vendor.c b/vendor.c
index d203d85..7610354 100644
--- a/vendor.c
+++ b/vendor.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 
diff --git a/wowlan.c b/wowlan.c
index 778c0db..71392d1 100644
--- a/wowlan.c
+++ b/wowlan.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: ISC */
+
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
-- 
2.17.0


^ permalink raw reply related

* Re: [PATCH v3 6/6] mm,thp: handle writes to file with THP in pagecache
From: Rik van Riel @ 2019-06-20 13:00 UTC (permalink / raw)
  To: Song Liu
  Cc: linux-mm@kvack.org, matthew.wilcox@oracle.com,
	kirill.shutemov@linux.intel.com, Kernel Team,
	william.kucharski@oracle.com, akpm@linux-foundation.org
In-Reply-To: <B051CE4A-063B-4464-8193-93C9F1D0A0A7@fb.com>

On Wed, 2019-06-19 at 22:10 -0400, Song Liu wrote:
> > On Jun 19, 2019, at 6:39 PM, Rik van Riel <riel@fb.com> wrote:
> > 
> > On Tue, 2019-06-18 at 23:24 -0700, Song Liu wrote:
> > 
> > > index 8563339041f6..bab8d9eef46c 100644
> > > --- a/mm/truncate.c
> > > +++ b/mm/truncate.c
> > > @@ -790,7 +790,11 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
> > > void truncate_pagecache(struct inode *inode, loff_t newsize)
> > > {
> > > 	struct address_space *mapping = inode->i_mapping;
> > > -	loff_t holebegin = round_up(newsize, PAGE_SIZE);
> > > +	loff_t holebegin;
> > > +
> > > +	/* if non-shmem file has thp, truncate the whole file */
> > > +	if (filemap_nr_thps(mapping))
> > > +		newsize = 0;
> > > 
> > 
> > I don't get it. Sometimes truncate is used to
> > increase the size of a file, or to change it
> > to a non-zero size.
> > 
> > Won't forcing the newsize to zero break applications,
> > when the file is truncated to a different size than
> > they expect?
> 
> This is not truncate the file. It only drops page cache. 
> truncate_setsize() will still set correct size. I don't 
> think this breaks anything. 

Ahhh, indeed. Good point.

I wonder if the dropping of the page cache could be
done automatically from open(), if it determines that
there are no more readonly THP users of the file, and
the new opener wants to write to the file?

That magic could be in a helper function, so it would
be just a one line change in the same spot where it
currently denies the permission :)

> We can probably make it smarter and only drop the clean
> huge pages (dirty page should not exist). 



^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.