diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 7ae9f6369a..07e2037e9b 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -836,6 +836,7 @@ static int create_xen_table(lpae_t *entry) enum xenmap_operation { INSERT, REMOVE, + MODIFY, RESERVE }; @@ -881,14 +882,28 @@ static int create_xen_entries(enum xenmap_operation op, 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: @@ -922,6 +937,12 @@ int destroy_xen_mappings(unsigned long v, unsigned long e) 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) { diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 05d9f82d0d..015ed6307a 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -65,6 +65,17 @@ #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. *