@@ -117,6 +117,29 @@ int altp2m_init_by_id(struct domain *d, unsigned int idx)
return rc;
}
+int altp2m_init_next_available(struct domain *d, uint16_t *idx)
+{
+ int rc = -EINVAL;
+ uint16_t i;
+
+ altp2m_lock(d);
+
+ for ( i = 0; i < MAX_ALTP2M; i++ )
+ {
+ if ( d->arch.altp2m_p2m[i] != NULL )
+ continue;
+
+ rc = altp2m_init_helper(d, i);
+ *idx = i;
+
+ break;
+ }
+
+ altp2m_unlock(d);
+
+ return rc;
+}
+
int altp2m_init(struct domain *d)
{
spin_lock_init(&d->arch.altp2m_lock);
@@ -126,7 +126,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
break;
case HVMOP_altp2m_create_p2m:
- rc = -EOPNOTSUPP;
+ if ( !(rc = altp2m_init_next_available(d, &a.u.view.view)) )
+ rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
break;
case HVMOP_altp2m_destroy_p2m:
@@ -53,6 +53,10 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
int altp2m_init_by_id(struct domain *d,
unsigned int idx);
+/* Find and initialize the next available alternate p2m. */
+int altp2m_init_next_available(struct domain *d,
+ uint16_t *idx);
+
/* Flush all the alternate p2m's for a domain. */
void altp2m_flush_complete(struct domain *d);