mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
arm/mpu: Introduce modify_after_init_mappings
During `init_done`, Xen sets the permissions of all symbols marked with __ro_after_init to be read-only. This does not work on MPU systems at present because part-region modification is not supported. Therefore introduce the function `modify_after_init_mappings` for MMU and MPU, to handle the divergent approaches to setting permissions of __ro_after_init symbols. For MPU systems `modify_xen_mappings` will shrink the RW mapping on one side and extend the RO mapping on the other. This approach prevents wasting an additional region between RW and RO mappings. As the new function is marked with __init, it needs to be called before `free_init_memory`. Signed-off-by: Luca Fancellu <luca.fancellu@arm.com> Signed-off-by: Hari Limaye <hari.limaye@arm.com> Signed-off-by: Harry Ramsey <harry.ramsey@arm.com> Reviewed-by: Michal Orzel <michal.orzel@amd.com>
This commit is contained in:
1 parent
342ac31d1f
commit
2dbdf8607c
5 files changed
+61
-14
No files matched your search
@@ -78,6 +78,9 @@ struct init_info
|
||||
paddr_t consider_modules(paddr_t s, paddr_t e, uint32_t size, paddr_t align,
|
||||
int first_mod);
|
||||
|
||||
/* Modify some mappings after the init is done */
|
||||
void modify_after_init_mappings(void);
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
@@ -213,6 +213,21 @@ void __init remove_early_mappings(void)
|
||||
BUG_ON(rc);
|
||||
}
|
||||
|
||||
void __init modify_after_init_mappings(void)
|
||||
{
|
||||
/*
|
||||
* We have finished booting. Mark the section .data.ro_after_init
|
||||
* read-only.
|
||||
*/
|
||||
int rc = modify_xen_mappings((unsigned long)&__ro_after_init_start,
|
||||
(unsigned long)&__ro_after_init_end,
|
||||
PAGE_HYPERVISOR_RO);
|
||||
|
||||
if ( rc )
|
||||
panic("Unable to mark the .data.ro_after_init section read-only (rc = %d)\n",
|
||||
rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* After boot, Xen page-tables should not contain mapping that are both
|
||||
* Writable and eXecutables.
|
||||
|
||||
@@ -35,7 +35,7 @@ DECLARE_BITMAP(xen_mpumap_mask, MAX_MPU_REGION_NR) \
|
||||
/* EL2 Xen MPU memory region mapping table. */
|
||||
pr_t __cacheline_aligned __section(".data") xen_mpumap[MAX_MPU_REGION_NR];
|
||||
|
||||
static DEFINE_SPINLOCK(xen_mpumap_lock);
|
||||
DEFINE_SPINLOCK(xen_mpumap_lock);
|
||||
|
||||
static void __init __maybe_unused build_assertions(void)
|
||||
{
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
#include <xen/pfn.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/sizes.h>
|
||||
#include <xen/spinlock.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
static paddr_t __initdata mapped_fdt_base = INVALID_PADDR;
|
||||
static paddr_t __initdata mapped_fdt_limit = INVALID_PADDR;
|
||||
|
||||
extern spinlock_t xen_mpumap_lock;
|
||||
|
||||
void __init setup_pagetables(void) {}
|
||||
|
||||
void * __init early_fdt_map(paddr_t fdt_paddr)
|
||||
@@ -106,6 +109,43 @@ void __init copy_from_paddr(void *dst, paddr_t paddr, unsigned long len)
|
||||
panic("Unable to unmap range for copy_from_paddr\n");
|
||||
}
|
||||
|
||||
void __init modify_after_init_mappings(void)
|
||||
{
|
||||
int rc;
|
||||
uint8_t idx_rodata;
|
||||
uint8_t idx_rwdata;
|
||||
|
||||
spin_lock(&xen_mpumap_lock);
|
||||
|
||||
rc = mpumap_contains_region(xen_mpumap, max_mpu_regions,
|
||||
(unsigned long)_srodata,
|
||||
(unsigned long)_erodata,
|
||||
&idx_rodata);
|
||||
|
||||
if ( rc < MPUMAP_REGION_FOUND )
|
||||
panic("Unable to find rodata section (rc = %d)\n", rc);
|
||||
|
||||
rc = mpumap_contains_region(xen_mpumap, max_mpu_regions,
|
||||
(unsigned long)__ro_after_init_start,
|
||||
(unsigned long)__init_begin,
|
||||
&idx_rwdata);
|
||||
|
||||
if ( rc < MPUMAP_REGION_FOUND )
|
||||
panic("Unable to find rwdata section (rc = %d)\n", rc);
|
||||
|
||||
/* Shrink rwdata section to begin at __ro_after_init_end */
|
||||
pr_set_base(&xen_mpumap[idx_rwdata], (unsigned long)__ro_after_init_end);
|
||||
|
||||
/* Extend rodata section to end at __ro_after_init_end */
|
||||
pr_set_limit(&xen_mpumap[idx_rodata], (unsigned long)__ro_after_init_end);
|
||||
|
||||
write_protection_region(&xen_mpumap[idx_rwdata], idx_rwdata);
|
||||
write_protection_region(&xen_mpumap[idx_rodata], idx_rodata);
|
||||
context_sync_mpu();
|
||||
|
||||
spin_unlock(&xen_mpumap_lock);
|
||||
}
|
||||
|
||||
void __init remove_early_mappings(void)
|
||||
{
|
||||
int rc = destroy_xen_mappings(round_pgdown(mapped_fdt_base),
|
||||
|
||||
+2
-13
@@ -66,23 +66,12 @@ domid_t __read_mostly max_init_domid;
|
||||
|
||||
static __used void noreturn init_done(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Must be done past setting system_state. */
|
||||
unregister_init_virtual_region();
|
||||
|
||||
free_init_memory();
|
||||
modify_after_init_mappings();
|
||||
|
||||
/*
|
||||
* We have finished booting. Mark the section .data.ro_after_init
|
||||
* read-only.
|
||||
*/
|
||||
rc = modify_xen_mappings((unsigned long)&__ro_after_init_start,
|
||||
(unsigned long)&__ro_after_init_end,
|
||||
PAGE_HYPERVISOR_RO);
|
||||
if ( rc )
|
||||
panic("Unable to mark the .data.ro_after_init section read-only (rc = %d)\n",
|
||||
rc);
|
||||
free_init_memory();
|
||||
|
||||
startup_cpu_idle_loop();
|
||||
}
|
||||
|
||||