[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v5 06/13] x86/domctl: Handle ACPI access from domctl



Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
---
Changes in v5:
* Code movement due to changes in patch 4

 xen/arch/x86/hvm/acpi.c | 64 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 55 insertions(+), 9 deletions(-)

diff --git a/xen/arch/x86/hvm/acpi.c b/xen/arch/x86/hvm/acpi.c
index b2299a4..044699d 100644
--- a/xen/arch/x86/hvm/acpi.c
+++ b/xen/arch/x86/hvm/acpi.c
@@ -7,9 +7,11 @@
 #include <xen/lib.h>
 #include <xen/sched.h>
 
+#include <asm/guest_access.h>
+
 #include <public/arch-x86/xen.h>
 
-static int acpi_cpumap_access_common(struct domain *d,
+static int acpi_cpumap_access_common(struct domain *d, bool is_guest_access,
                                      int dir, unsigned int port,
                                      unsigned int bytes, uint32_t *val)
 {
@@ -32,14 +34,15 @@ static int acpi_cpumap_access_common(struct domain *d,
             memcpy(val, (uint8_t *)d->avail_vcpus + first_byte,
                    min(bytes, ((d->max_vcpus + 7) / 8) - first_byte));
     }
-    else
+    else if ( !is_guest_access )
         /* Guests do not write CPU map */
-        return X86EMUL_UNHANDLEABLE;
+        memcpy((uint8_t *)d->avail_vcpus + first_byte, val,
+               min(bytes, ((d->max_vcpus + 7) / 8) - first_byte));
 
     return X86EMUL_OKAY;
 }
 
-static int acpi_access_common(struct domain *d,
+static int acpi_access_common(struct domain *d, bool is_guest_access,
                               int dir, unsigned int port,
                               unsigned int bytes, uint32_t *val)
 {
@@ -96,14 +99,20 @@ static int acpi_access_common(struct domain *d,
         switch ( port & 3 )
         {
         case 0:
-            *sts &= ~(v & 0xff);
+            if ( is_guest_access )
+                *sts &= ~(v & 0xff);
+            else
+                *sts = (*sts & 0xff00) | (v & 0xff);
             *sts &= *mask_sts;
             if ( !--bytes )
                 break;
             v >>= 8;
             /* fallthrough */
         case 1:
-            *sts &= ~((v & 0xff) << 8);
+            if ( is_guest_access )
+                *sts &= ~((v & 0xff) << 8);
+            else
+                *sts = ((v & 0xff) << 8) | (*sts & 0xff);
             *sts &= *mask_sts;
             if ( !--bytes )
                 break;
@@ -129,13 +138,50 @@ int hvm_acpi_domctl_access(struct domain *d, uint8_t rw,
                            const xen_acpi_access_t *access,
                            XEN_GUEST_HANDLE_PARAM(void) arg)
 {
-    return -ENOSYS;
+    unsigned int bytes, i;
+    uint32_t val;
+    uint8_t *ptr = (uint8_t *)&val;
+    int rc;
+    int (*do_acpi_access)(struct domain *d, bool is_guest_access,
+                          int dir, unsigned int port,
+                          unsigned int bytes, uint32_t *val);
+
+    if ( has_acpi_dm_ff(d) )
+        return -EINVAL;
+
+    if ( access->space_id != XEN_ACPI_SYSTEM_IO )
+        return -EINVAL;
+
+    if ( (access->address >= XEN_ACPI_CPU_MAP) &&
+         (access->address < XEN_ACPI_CPU_MAP + XEN_ACPI_CPU_MAP_LEN) )
+        do_acpi_access = acpi_cpumap_access_common;
+    else
+        do_acpi_access = acpi_access_common;
+
+    for ( i = 0; i < access->width; i += sizeof(val) )
+    {
+        bytes = (access->width - i > sizeof(val)) ? sizeof(val) : 
access->width - i;
+
+        if ( (rw == XEN_DOMCTL_ACPI_WRITE) &&
+             copy_from_guest_offset(ptr, arg, i, bytes) )
+            return -EFAULT;
+
+        rc = do_acpi_access(d, false, rw, access->address, bytes, &val);
+        if ( rc )
+            return rc;
+
+        if ( (rw == XEN_DOMCTL_ACPI_READ) &&
+             copy_to_guest_offset(arg, i, ptr, bytes) )
+            return -EFAULT;
+    }
+
+    return 0;
 }
 
 static int acpi_guest_access(int dir, unsigned int port,
                              unsigned int bytes, uint32_t *val)
 {
-    return  acpi_access_common(current->domain,
+    return  acpi_access_common(current->domain, true,
                                (dir == IOREQ_READ) ?
                                XEN_DOMCTL_ACPI_READ: XEN_DOMCTL_ACPI_WRITE,
                                port, bytes, val);
@@ -144,7 +190,7 @@ static int acpi_guest_access(int dir, unsigned int port,
 static int acpi_cpumap_guest_access(int dir, unsigned int port,
                                     unsigned int bytes, uint32_t *val)
 {
-    return  acpi_cpumap_access_common(current->domain,
+    return  acpi_cpumap_access_common(current->domain, true,
                                       (dir == IOREQ_READ) ?
                                       XEN_DOMCTL_ACPI_READ: 
XEN_DOMCTL_ACPI_WRITE,
                                       port, bytes, val);
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.