@@ -118,6 +118,50 @@ extern void __set_fixmap_x(
#define __fix_x_to_virt(x) (FIXADDR_X_TOP - ((x) << PAGE_SHIFT))
#define fix_x_to_virt(x) ((void *)__fix_x_to_virt(x))
+/* per-CPU fixmap area. */
+enum percpu_fixed_addresses {
+ __end_of_percpu_fixed_addresses
+};
+
+#define PERCPU_FIXADDR_SIZE (__end_of_percpu_fixed_addresses << PAGE_SHIFT)
+#define PERCPU_FIXADDR PERCPU_VIRT_SLOT(0)
+
+static inline void *percpu_fix_to_virt(enum percpu_fixed_addresses idx)
+{
+ BUG_ON(idx >=__end_of_percpu_fixed_addresses);
+ return (void *)PERCPU_FIXADDR + (idx << PAGE_SHIFT);
+}
+
+static inline void percpu_set_fixmap_remote(
+ unsigned int cpu, enum percpu_fixed_addresses idx, mfn_t mfn,
+ unsigned long flags)
+{
+ map_pages_to_xen_cpu((unsigned long)percpu_fix_to_virt(idx), mfn, 1, flags,
+ cpu);
+}
+
+static inline void percpu_clear_fixmap_remote(
+ unsigned int cpu, enum percpu_fixed_addresses idx)
+{
+ /*
+ * Use map_pages_to_xen_cpu() instead of destroy_xen_mappings_cpu() to
+ * avoid tearing down the intermediate page-tables if empty.
+ */
+ map_pages_to_xen_cpu((unsigned long)percpu_fix_to_virt(idx), INVALID_MFN, 1,
+ 0, cpu);
+}
+
+static inline void percpu_set_fixmap(enum percpu_fixed_addresses idx, mfn_t mfn,
+ unsigned long flags)
+{
+ percpu_set_fixmap_remote(smp_processor_id(), idx, mfn, flags);
+}
+
+static inline void percpu_clear_fixmap(enum percpu_fixed_addresses idx)
+{
+ percpu_clear_fixmap_remote(smp_processor_id(), idx);
+}
+
#endif /* __ASSEMBLY__ */
#endif
@@ -6467,7 +6467,17 @@ int allocate_perdomain_local_l3(unsigned int cpu)
per_cpu(local_l3, cpu) = l3;
- return 0;
+ /*
+ * Pre-allocate the page-table structures for the per-cpu fixmap. Some of
+ * the per-cpu fixmap calls might happen in contexts where memory
+ * allocation is not possible.
+ *
+ * Only one L3 slot is currently reserved for the per-CPU fixmap.
+ */
+ BUILD_BUG_ON(PERCPU_FIXADDR_SIZE > (1 << L3_PAGETABLE_SHIFT));
+ return map_pages_to_xen_cpu(PERCPU_VIRT_START, INVALID_MFN,
+ PFN_DOWN(PERCPU_FIXADDR_SIZE), MAP_SMALL_PAGES,
+ cpu);
}
void free_perdomain_local_l3(unsigned int cpu)
@@ -6478,6 +6488,10 @@ void free_perdomain_local_l3(unsigned int cpu)
return;
per_cpu(local_l3, cpu) = NULL;
+
+ destroy_xen_mappings_cpu(PERCPU_VIRT_START,
+ PERCPU_VIRT_START + PERCPU_FIXADDR_SIZE, cpu);
+
free_xenheap_page(l3);
}
Introduce the logic to manage a per-CPU fixmap area. This includes adding a new set of headers that are capable of creating mappings in the per-CPU page-table regions by making use of the map_pages_to_xen_cpu(). This per-CPU fixmap area is currently set to use one L3 slot: 1GiB of linear address space. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- xen/arch/x86/include/asm/fixmap.h | 44 +++++++++++++++++++++++++++++++ xen/arch/x86/mm.c | 16 ++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-)