@@ -55,6 +55,7 @@ obj-y += pci.o
obj-y += percpu.o
obj-y += physdev.o x86_64/physdev.o
obj-y += platform_hypercall.o x86_64/platform_hypercall.o
+obj-y += pmap.o
obj-y += psr.o
obj-y += setup.o
obj-y += shutdown.o
new file mode 100644
@@ -0,0 +1,82 @@
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/spinlock.h>
+
+#include <asm/bitops.h>
+#include <asm/fixmap.h>
+
+/*
+ * Simple mapping infrastructure to map / unmap pages in fixed map.
+ * This is used to set up percpu page table for mapcache, which is
+ * used by map domain page infrastructure.
+ *
+ * There is a restriction that only one CPU can use this
+ * infrastructure at a time. So this infrastructure _should not_ be
+ * used anywhere else other than the stated purpose above.
+ */
+
+static DEFINE_SPINLOCK(lock);
+/* Bitmap to track which slot is used */
+static unsigned long inuse;
+
+void pmap_lock(void)
+{
+ spin_lock(&lock);
+}
+
+void pmap_unlock(void)
+{
+ spin_unlock(&lock);
+}
+
+void *pmap_map(struct page_info *page)
+{
+ unsigned int idx;
+ void *linear = NULL;
+ enum fixed_addresses slot;
+
+ ASSERT(!in_irq());
+ ASSERT(spin_is_locked(&lock));
+
+ idx = find_first_zero_bit(&inuse, NUM_FIX_PMAP);
+ if ( idx == NUM_FIX_PMAP )
+ panic("Out of PMAP slots\n");
+
+ __set_bit(idx, &inuse);
+
+ slot = idx + FIX_PMAP_BEGIN;
+ ASSERT(slot >= FIX_PMAP_BEGIN && slot <= FIX_PMAP_END);
+
+ set_fixmap(slot, mfn_x(page_to_mfn(page)));
+ linear = (void *)__fix_to_virt(slot);
+
+ return linear;
+}
+
+void pmap_unmap(void *p)
+{
+ unsigned int idx;
+ enum fixed_addresses slot = __virt_to_fix((unsigned long)p);
+
+ ASSERT(!in_irq());
+ ASSERT(slot >= FIX_PMAP_BEGIN && slot <= FIX_PMAP_END);
+ ASSERT(spin_is_locked(&lock));
+
+ idx = slot - FIX_PMAP_BEGIN;
+ __clear_bit(idx, &inuse);
+ clear_fixmap(slot);
+}
+
+static void __maybe_unused build_assertions(void)
+{
+ BUILD_BUG_ON(sizeof(inuse) * BITS_PER_LONG < NUM_FIX_PMAP);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
@@ -23,6 +23,7 @@
#include <xen/kexec.h>
#include <asm/apicdef.h>
#include <asm/msi.h>
+#include <asm/pmap.h>
#include <acpi/apei.h>
/*
@@ -48,6 +49,8 @@ enum fixed_addresses {
FIX_XEN_SHARED_INFO,
#endif /* CONFIG_XEN_GUEST */
/* Everything else should go further down. */
+ FIX_PMAP_BEGIN,
+ FIX_PMAP_END = FIX_PMAP_BEGIN + NUM_FIX_PMAP - 1,
FIX_APIC_BASE,
FIX_IO_APIC_BASE_0,
FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
new file mode 100644
@@ -0,0 +1,12 @@
+#ifndef __X86_PMAP_H__
+#define __X86_PMAP_H__
+
+/* Large enough for mapping 5 levels of page tables */
+#define NUM_FIX_PMAP 5
+
+void pmap_lock(void);
+void pmap_unlock(void);
+void *pmap_map(struct page_info *page);
+void pmap_unmap(void *p);
+
+#endif /* __X86_PMAP_H__ */