arm/mpu: Implement p2m tables

Implement `p2m_alloc_table`, `p2m_init` and `p2m_final_teardown` for MPU
systems.

Signed-off-by: Harry Ramsey <harry.ramsey@arm.com>
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
This commit is contained in:
Harry Ramsey authored and Michal Orzel committed 2026-05-15 09:08:19 +02:00
1 parent 1afacf7b15
commit cd5fe09e50
5 files changed
+86 -3

No files matched your search

+2
View File
@@ -11,6 +11,8 @@
*/
#define MPU_REGION_RES0 0x0
#define VSCTLR_VMID_SHIFT 16
/* Hypervisor Protection Region Base Address Register */
typedef union {
struct {
+2
View File
@@ -7,6 +7,8 @@
#define MPU_REGION_RES0 (0xFFFFULL << 48)
#define VSCTLR_VMID_SHIFT 48
/* Protection Region Base Address Register */
typedef union {
struct __packed {
+8
View File
@@ -3,8 +3,16 @@
#ifndef __ARM_MPU_P2M_H__
#define __ARM_MPU_P2M_H__
#include <xen/bitops.h>
#include <xen/macros.h>
#include <xen/page-size.h>
#include <asm/mpu.h>
struct p2m_domain;
#define P2M_ROOT_PAGES DIV_ROUND_UP(MAX_MPU_REGION_NR * sizeof(pr_t), PAGE_SIZE)
#define P2M_ROOT_ORDER get_count_order(P2M_ROOT_PAGES)
static inline void p2m_clear_root_pages(struct p2m_domain *p2m) {}
static inline void p2m_tlb_flush_sync(struct p2m_domain *p2m) {}
+5
View File
@@ -51,8 +51,13 @@ struct p2m_domain {
/* Current VMID in use */
uint16_t vmid;
#ifdef CONFIG_MMU
/* Current Translation Table Base Register for the p2m */
uint64_t vttbr;
#else
/* Current Virtualization System Control Register for the p2m */
register_t vsctlr;
#endif
/* Highest guest frame that's ever been mapped in the p2m */
gfn_t max_mapped_gfn;
+69 -3
View File
@@ -28,10 +28,63 @@ void p2m_dump_info(struct domain *d)
BUG_ON("unimplemented");
}
static int p2m_alloc_table(struct domain *d)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
void *table = alloc_xenheap_pages(P2M_ROOT_ORDER, 0);
unsigned int i;
if ( !table )
{
printk(XENLOG_G_ERR "%pd: p2m: unable to allocate P2M MPU mapping table\n",
d);
return -ENOMEM;
}
p2m->root = virt_to_page(table);
for ( i = 0; i < P2M_ROOT_PAGES; i++ )
clear_page(table + (i * PAGE_SIZE));
return 0;
}
int p2m_init(struct domain *d)
{
BUG_ON("unimplemented");
return -EINVAL;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
int rc = 0;
unsigned int cpu;
rwlock_init(&p2m->lock);
p2m->vmid = INVALID_VMID;
p2m->max_mapped_gfn = _gfn(0);
p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
p2m->default_access = p2m_access_rwx;
/* mem_access is NOT supported on MPU system. */
p2m->mem_access_enabled = false;
/* Ensure that the type chosen is large enough for MAX_VIRT_CPUS. */
BUILD_BUG_ON((1 << (sizeof(p2m->last_vcpu_ran[0]) * 8)) < MAX_VIRT_CPUS);
BUILD_BUG_ON((1 << (sizeof(p2m->last_vcpu_ran[0]) * 8)) < INVALID_VCPU_ID);
for_each_possible_cpu(cpu)
p2m->last_vcpu_ran[cpu] = INVALID_VCPU_ID;
/*
* "Trivial" initialization is now complete. Set the backpointer so that
* p2m_teardown() and related functions know to do something.
*/
p2m->domain = d;
rc = p2m_alloc_vmid(d);
if ( rc )
return rc;
p2m->vsctlr = ((register_t)p2m->vmid << VSCTLR_VMID_SHIFT);
return p2m_alloc_table(d);
}
void p2m_save_state(struct vcpu *p)
@@ -46,7 +99,20 @@ void p2m_restore_state(struct vcpu *n)
void p2m_final_teardown(struct domain *d)
{
BUG_ON("unimplemented");
struct p2m_domain *p2m = p2m_get_hostp2m(d);
/* p2m not actually initialized */
if ( !p2m->domain )
return;
if ( p2m->root )
free_xenheap_pages(page_to_virt(p2m->root), P2M_ROOT_ORDER);
p2m->root = NULL;
p2m_free_vmid(d);
p2m->domain = NULL;
}
bool p2m_resolve_translation_fault(struct domain *d, gfn_t gfn)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.