--- /dev/null
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/spinlock.h>
+
+#include <asm/bitops.h>
+#include <asm/fixmap.h>
+#include <asm/flushtlb.h>
+
+/*
+ * Simple mapping infrastructure to map / unmap pages in fixed map.
+ * This is used to set up the 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_cpu);
+/* Bitmap to track which slot is used */
+static unsigned long inuse;
+
+/* which pCPU is using PMAP at the moment */
+static unsigned int lock_cpu_id = ~0;
+/* how many entries has the current pCPU mapped */
+static unsigned int lock_count;
+
+static void pmap_cpu_up(void)
+{
+ int success = 0;
+ unsigned int cpu_id = smp_processor_id();
+
+ do
+ {
+ while ( cpu_id != lock_cpu_id && lock_count != 0 )
+ ;
+ spin_lock(&lock_cpu);
+ if ( cpu_id == lock_cpu_id || lock_count == 0 )
+ {
+ lock_cpu_id = cpu_id;
+ lock_count++;
+ success = 1;
+ }
+ spin_unlock(&lock_cpu);
+ } while ( !success );
+}
+
+static void pmap_cpu_down(void)
+{
+ spin_lock(&lock_cpu);
+ ASSERT(smp_processor_id() == lock_cpu_id);
+ ASSERT(lock_count);
+ lock_count--;
+ spin_unlock(&lock_cpu);
+}
+
+void *pmap_map(mfn_t mfn)
+{
+ unsigned long flags;
+ unsigned int idx;
+ void *linear = NULL;
+ enum fixed_addresses slot;
+ l1_pgentry_t *pl1e;
+
+ ASSERT(!in_irq());
+
+ local_irq_save(flags);
+ pmap_cpu_up();
+
+ 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);
+
+ pl1e = &l1_fixmap[L1_PAGETABLE_ENTRIES - 1 - slot];
+ l1e_write_atomic(pl1e, l1e_from_mfn(mfn, PAGE_HYPERVISOR));
+ linear = (void *)__fix_to_virt(slot);
+ flush_tlb_one_local(linear);
+
+ local_irq_restore(flags);
+ return linear;
+}
+
+void pmap_unmap(void *p)
+{
+ unsigned long flags;
+ unsigned int idx;
+ l1_pgentry_t *pl1e;
+ enum fixed_addresses slot = __virt_to_fix((unsigned long)p);
+
+ ASSERT(!in_irq());
+ ASSERT(slot >= FIX_PMAP_BEGIN && slot <= FIX_PMAP_END);
+
+ idx = slot - FIX_PMAP_BEGIN;
+ local_irq_save(flags);
+
+ __clear_bit(idx, &inuse);
+ pl1e = &l1_fixmap[L1_PAGETABLE_ENTRIES - 1 - slot];
+ l1e_write_atomic(pl1e, l1e_from_mfn(_mfn(0), 0));
+ flush_tlb_one_local(p);
+
+ pmap_cpu_down();
+ local_irq_restore(flags);
+}
+
+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:
+ */