enum xenmap_operation {
INSERT,
REMOVE,
+ MODIFY,
RESERVE
};
pte.pt.table = 1;
write_pte(&third[third_table_offset(addr)], pte);
break;
+ case MODIFY:
case REMOVE:
if ( !third[third_table_offset(addr)].pt.valid )
{
- printk("create_xen_entries: trying to remove a non-existing mapping addr=%lx\n",
- addr);
+ printk("create_xen_entries: trying to %s a non-existing mapping addr=%lx\n",
+ op == REMOVE ? "remove" : "modify", addr);
return -EINVAL;
}
- pte.bits = 0;
+ if ( op == REMOVE )
+ pte.bits = 0;
+ else
+ {
+ pte = third[third_table_offset(addr)];
+ pte.pt.ro = PTE_RO_MASK(ai);
+ pte.pt.xn = PTE_NX_MASK(ai);
+ if ( !pte.pt.ro && !pte.pt.xn )
+ {
+ printk("create_xen_entries: Incorrect combination for addr=%lx\n",
+ addr);
+ return -EINVAL;
+ }
+ }
write_pte(&third[third_table_offset(addr)], pte);
break;
default:
return create_xen_entries(REMOVE, v, 0, (e - v) >> PAGE_SHIFT, 0);
}
+int modify_xen_mappings(unsigned long s, unsigned long e, unsigned int flags)
+{
+ ASSERT((flags & (PTE_NX | PTE_RO)) == flags);
+ return create_xen_entries(MODIFY, s, 0, (e - s) >> PAGE_SHIFT, flags);
+}
+
enum mg { mg_clear, mg_ro, mg_rw, mg_rx };
static void set_pte_flags_on_range(const char *p, unsigned long l, enum mg mg)
{
#define PAGE_HYPERVISOR_NOCACHE (DEV_SHARED)
#define PAGE_HYPERVISOR_WC (DEV_WC)
+/*
+ * Defines for changing the hypervisor PTE .ro and .nx bits. This is only to be
+ * used with modify_xen_mappings.
+ */
+#define _PTE_NX_BIT 0U
+#define _PTE_RO_BIT 1U
+#define PTE_NX (1U << _PTE_NX_BIT)
+#define PTE_RO (1U << _PTE_RO_BIT)
+#define PTE_NX_MASK(x) (((x) >> _PTE_NX_BIT) & 0x1U)
+#define PTE_RO_MASK(x) (((x) >> _PTE_RO_BIT) & 0x1U)
+
/*
* Stage 2 Memory Type.
*