#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 {
+ /* Index 0 is reserved since fix_to_virt(0) == FIXADDR_TOP. */
+ PCPU_FIX_RESERVED,
+ PCPU_FIX_PV_L4SHADOW,
+ __end_of_percpu_fixed_addresses
+};
+
+#define PERCPU_FIXADDR_SIZE (__end_of_percpu_fixed_addresses << PAGE_SHIFT)
+#define PERCPU_FIXADDR_TOP (PERCPU_VIRT_SLOT(0) + PERCPU_FIXADDR_SIZE - \
+ PAGE_SIZE)
+
+static inline void *percpu_fix_to_virt(enum percpu_fixed_addresses idx)
+{
+ BUG_ON(idx >=__end_of_percpu_fixed_addresses || idx <= PCPU_FIX_RESERVED);
+ return (void *)PERCPU_FIXADDR_TOP - (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)
+{
+ 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
clear_page(l2);
clear_page(l1);
+ /* Ensure one L1 table is enough to cover for the per-CPU fixmap. */
+ BUILD_BUG_ON(PERCPU_FIXADDR_SIZE > (1U << L2_PAGETABLE_SHIFT));
+
l3[l3_table_offset(PERCPU_VIRT_START)] =
l3e_from_mfn(virt_to_mfn(l2), __PAGE_HYPERVISOR_RW);
l2[l2_table_offset(PERCPU_VIRT_START)] =
}
if ( is_pv_domain(d) )
- map_pages_to_xen(PERCPU_VIRT_START, v->arch.pv.guest_l4, 1,
- __PAGE_HYPERVISOR_RO);
+ percpu_set_fixmap(PCPU_FIX_PV_L4SHADOW, v->arch.pv.guest_l4,
+ __PAGE_HYPERVISOR_RO);
else
- destroy_xen_mappings(PERCPU_VIRT_START,
- PERCPU_VIRT_START + PAGE_SIZE);
+ percpu_clear_fixmap(PCPU_FIX_PV_L4SHADOW);
root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
l4e_from_mfn(virt_to_mfn(l3), __PAGE_HYPERVISOR_RW);
#include <xen/guest_access.h>
#include <asm/current.h>
+#include <asm/fixmap.h>
#include <asm/p2m.h>
#include "mm.h"
ASSERT(mfn_eq(maddr_to_mfn(v->arch.cr3),
_mfn(virt_to_mfn(this_cpu(root_pgt)))));
- copy_page(this_cpu(root_pgt), (void *)PERCPU_VIRT_START);
+ copy_page(this_cpu(root_pgt), percpu_fix_to_virt(PCPU_FIX_PV_L4SHADOW));
setup_perdomain_slot(v, this_cpu(root_pgt));
}
v->arch.pv.guest_l4 = mfn;
if ( this_cpu(root_pgt) )
- map_pages_to_xen(PERCPU_VIRT_START, v->arch.pv.guest_l4, 1,
- __PAGE_HYPERVISOR_RO);
+ percpu_set_fixmap(PCPU_FIX_PV_L4SHADOW, v->arch.pv.guest_l4,
+ __PAGE_HYPERVISOR_RO);
/*
* No need to copy the contents of the guest L4 to the per-CPU shadow.