|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |