arm: export platform_op XENPF_settime64
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Thu, 12 Nov 2015 17:46:03 +0000 (17:46 +0000)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 25 Nov 2015 11:26:25 +0000 (11:26 +0000)
Call update_domain_wallclock_time at domain initialization.
Set time_offset_seconds to the number of seconds between physical boot
and domain initialization: it is going to be used to get/set the
wallclock time.
Add time_offset_seconds to system_time when before calling do_settime,
so that system_time actually accounts for all the time in nsec between
machine boot and when the wallclock was set.

Expose xsm_platform_op to ARM.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Reviewed-by: Julien Grall <julien.grall@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
CC: dgdegra@tycho.nsa.gov
xen/arch/arm/Makefile
xen/arch/arm/domain.c
xen/arch/arm/platform_hypercall.c [new file with mode: 0644]
xen/arch/arm/traps.c
xen/arch/arm/vtimer.c
xen/include/xsm/dummy.h
xen/include/xsm/xsm.h
xen/xsm/dummy.c
xen/xsm/flask/hooks.c

index e47dd4c5164f786fac08d5285a1a4977ae7e1144..4ac5eddec43857ed8c954b8348cde8674e9251e3 100644 (file)
@@ -23,6 +23,7 @@ obj-y += percpu.o
 obj-y += guestcopy.o
 obj-y += physdev.o
 obj-y += platform.o
+obj-y += platform_hypercall.o
 obj-y += setup.o
 obj-y += bootfdt.o
 obj-y += time.o
index 1b0f9ebae6b491daac8eb9d7009cec6e11f11481..860ac7db0cc014e93e41bd31d8f8fea915e09d1c 100644 (file)
@@ -595,6 +595,8 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags,
     if ( (rc = domain_vtimer_init(d, config)) != 0 )
         goto fail;
 
+    update_domain_wallclock_time(d);
+
     /*
      * The hardware domain will get a PPI later in
      * arch/arm/domain_build.c  depending on the
diff --git a/xen/arch/arm/platform_hypercall.c b/xen/arch/arm/platform_hypercall.c
new file mode 100644 (file)
index 0000000..b708711
--- /dev/null
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * platform_hypercall.c
+ *
+ * Hardware platform operations. Intended for use by domain-0 kernel.
+ *
+ * Copyright (c) 2015, Citrix
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/guest_access.h>
+#include <xen/spinlock.h>
+#include <public/platform.h>
+#include <xsm/xsm.h>
+#include <asm/current.h>
+#include <asm/event.h>
+
+DEFINE_SPINLOCK(xenpf_lock);
+
+long do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
+{
+    long ret;
+    struct xen_platform_op curop, *op = &curop;
+    struct domain *d;
+
+    if ( copy_from_guest(op, u_xenpf_op, 1) )
+        return -EFAULT;
+
+    if ( op->interface_version != XENPF_INTERFACE_VERSION )
+        return -EACCES;
+
+    d = rcu_lock_current_domain();
+    if ( d == NULL )
+        return -ESRCH;
+
+    ret = xsm_platform_op(XSM_PRIV, op->cmd);
+    if ( ret )
+        return ret;
+
+    /*
+     * Trylock here avoids deadlock with an existing platform critical section
+     * which might (for some current or future reason) want to synchronise
+     * with this vcpu.
+     */
+    while ( !spin_trylock(&xenpf_lock) )
+        if ( hypercall_preempt_check() )
+            return hypercall_create_continuation(
+                __HYPERVISOR_platform_op, "h", u_xenpf_op);
+
+    switch ( op->cmd )
+    {
+    case XENPF_settime64:
+        if ( likely(!op->u.settime64.mbz) )
+            do_settime(op->u.settime64.secs,
+                       op->u.settime64.nsecs,
+                       op->u.settime64.system_time + SECONDS(d->time_offset_seconds));
+        else
+            ret = -EINVAL;
+        break;
+
+    default:
+        ret = -ENOSYS;
+        break;
+    }
+
+    spin_unlock(&xenpf_lock);
+    rcu_unlock_domain(d);
+    return ret;
+}
index 9d2bd6a7d8676ec73b54c2f8d102b98159982d0b..c49bd3fa712f6b7cb79542aeb93e943ce8cc6477 100644 (file)
@@ -1233,6 +1233,7 @@ static arm_hypercall_t arm_hypercall_table[] = {
     HYPERCALL(hvm_op, 2),
     HYPERCALL(grant_table_op, 3),
     HYPERCALL(multicall, 2),
+    HYPERCALL(platform_op, 1),
     HYPERCALL_ARM(vcpu_op, 3),
 };
 
index 1418092aeb0c82add5e2466eaea65da18da43001..c8e2a12dfe0cd47d3c06b2d4fb0b05d6d39b58b5 100644 (file)
@@ -22,6 +22,7 @@
 #include <xen/timer.h>
 #include <xen/sched.h>
 #include <xen/perfc.h>
+#include <asm/div64.h>
 #include <asm/irq.h>
 #include <asm/time.h>
 #include <asm/gic.h>
@@ -64,6 +65,8 @@ int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig *config)
 {
     d->arch.phys_timer_base.offset = NOW();
     d->arch.virt_timer_base.offset = READ_SYSREG64(CNTPCT_EL0);
+    d->time_offset_seconds = ticks_to_ns(d->arch.virt_timer_base.offset - boot_count);
+    do_div(d->time_offset_seconds, 1000000000);
 
     config->clock_frequency = timer_dt_clock_frequency;
 
index 9fe372ce3069a437b855ca6694ae4b1a6812741a..e43f2a1967ad7e95c725ebe902111465107a5de3 100644 (file)
@@ -584,6 +584,12 @@ static XSM_INLINE int xsm_mem_sharing(XSM_DEFAULT_ARG struct domain *d)
 }
 #endif
 
+static XSM_INLINE int xsm_platform_op(XSM_DEFAULT_ARG uint32_t op)
+{
+    XSM_ASSERT_ACTION(XSM_PRIV);
+    return xsm_default_action(action, current->domain, NULL);
+}
+
 #ifdef CONFIG_X86
 static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID)
 {
@@ -639,12 +645,6 @@ static XSM_INLINE int xsm_apic(XSM_DEFAULT_ARG struct domain *d, int cmd)
     return xsm_default_action(action, d, NULL);
 }
 
-static XSM_INLINE int xsm_platform_op(XSM_DEFAULT_ARG uint32_t op)
-{
-    XSM_ASSERT_ACTION(XSM_PRIV);
-    return xsm_default_action(action, current->domain, NULL);
-}
-
 static XSM_INLINE int xsm_machine_memory_map(XSM_DEFAULT_VOID)
 {
     XSM_ASSERT_ACTION(XSM_PRIV);
index ba3caedd9e2266343424f1a038f0323b49202739..f48cf604911d1d1acf40caa64a1b88d131e2a3db 100644 (file)
@@ -164,6 +164,8 @@ struct xsm_operations {
     int (*mem_sharing) (struct domain *d);
 #endif
 
+    int (*platform_op) (uint32_t cmd);
+
 #ifdef CONFIG_X86
     int (*do_mca) (void);
     int (*shadow_control) (struct domain *d, uint32_t op);
@@ -175,7 +177,6 @@ struct xsm_operations {
     int (*mem_sharing_op) (struct domain *d, struct domain *cd, int op);
     int (*apic) (struct domain *d, int cmd);
     int (*memtype) (uint32_t access);
-    int (*platform_op) (uint32_t cmd);
     int (*machine_memory_map) (void);
     int (*domain_memory_map) (struct domain *d);
 #define XSM_MMU_UPDATE_READ      1
@@ -624,6 +625,11 @@ static inline int xsm_mem_sharing (xsm_default_t def, struct domain *d)
 }
 #endif
 
+static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
+{
+    return xsm_ops->platform_op(op);
+}
+
 #ifdef CONFIG_X86
 static inline int xsm_do_mca(xsm_default_t def)
 {
@@ -675,11 +681,6 @@ static inline int xsm_memtype (xsm_default_t def, uint32_t access)
     return xsm_ops->memtype(access);
 }
 
-static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
-{
-    return xsm_ops->platform_op(op);
-}
-
 static inline int xsm_machine_memory_map(xsm_default_t def)
 {
     return xsm_ops->machine_memory_map();
index 72eba40056acce057ad8133955fb17b48fee1559..618a96eaf6d2fb3083cadf8bf8539e77b92f4018 100644 (file)
@@ -141,6 +141,7 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, mem_sharing);
 #endif
 
+    set_to_dummy_if_null(ops, platform_op);
 #ifdef CONFIG_X86
     set_to_dummy_if_null(ops, do_mca);
     set_to_dummy_if_null(ops, shadow_control);
@@ -151,7 +152,6 @@ void xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, hvm_ioreq_server);
     set_to_dummy_if_null(ops, mem_sharing_op);
     set_to_dummy_if_null(ops, apic);
-    set_to_dummy_if_null(ops, platform_op);
     set_to_dummy_if_null(ops, machine_memory_map);
     set_to_dummy_if_null(ops, domain_memory_map);
     set_to_dummy_if_null(ops, mmu_update);
index 4180f3babd6449d85a49c8de4f5c55e0aa148d71..da8d2870632eb2ac1fe10fd5019ee89802fe565e 100644 (file)
@@ -1335,6 +1335,75 @@ static int flask_deassign_dtdevice(struct domain *d, const char *dtpath)
 }
 #endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
 
+static int flask_platform_op(uint32_t op)
+{
+    switch ( op )
+    {
+#ifdef CONFIG_X86
+    /* These operations have their own XSM hooks */
+    case XENPF_cpu_online:
+    case XENPF_cpu_offline:
+    case XENPF_cpu_hotadd:
+    case XENPF_mem_hotadd:
+        return 0;
+#endif
+
+    case XENPF_settime32:
+    case XENPF_settime64:
+        return domain_has_xen(current->domain, XEN__SETTIME);
+
+    case XENPF_add_memtype:
+        return domain_has_xen(current->domain, XEN__MTRR_ADD);
+
+    case XENPF_del_memtype:
+        return domain_has_xen(current->domain, XEN__MTRR_DEL);
+
+    case XENPF_read_memtype:
+        return domain_has_xen(current->domain, XEN__MTRR_READ);
+
+    case XENPF_microcode_update:
+        return domain_has_xen(current->domain, XEN__MICROCODE);
+
+    case XENPF_platform_quirk:
+        return domain_has_xen(current->domain, XEN__QUIRK);
+
+    case XENPF_firmware_info:
+        return domain_has_xen(current->domain, XEN__FIRMWARE);
+
+    case XENPF_efi_runtime_call:
+        return domain_has_xen(current->domain, XEN__FIRMWARE);
+
+    case XENPF_enter_acpi_sleep:
+        return domain_has_xen(current->domain, XEN__SLEEP);
+
+    case XENPF_change_freq:
+        return domain_has_xen(current->domain, XEN__FREQUENCY);
+
+    case XENPF_getidletime:
+        return domain_has_xen(current->domain, XEN__GETIDLE);
+
+    case XENPF_set_processor_pminfo:
+    case XENPF_core_parking:
+        return domain_has_xen(current->domain, XEN__PM_OP);
+
+    case XENPF_get_cpu_version:
+    case XENPF_get_cpuinfo:
+        return domain_has_xen(current->domain, XEN__GETCPUINFO);
+
+    case XENPF_resource_op:
+        return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2,
+                                    XEN2__RESOURCE_OP, NULL);
+
+    case XENPF_get_symbol:
+        return avc_has_perm(domain_sid(current->domain), SECINITSID_XEN,
+                            SECCLASS_XEN2, XEN2__GET_SYMBOL, NULL);
+
+    default:
+        printk("flask_platform_op: Unknown op %d\n", op);
+        return -EPERM;
+    }
+}
+
 #ifdef CONFIG_X86
 static int flask_do_mca(void)
 {
@@ -1473,75 +1542,6 @@ static int flask_apic(struct domain *d, int cmd)
     return domain_has_xen(d, perm);
 }
 
-static int flask_platform_op(uint32_t op)
-{
-    switch ( op )
-    {
-#ifdef CONFIG_X86
-    /* These operations have their own XSM hooks */
-    case XENPF_cpu_online:
-    case XENPF_cpu_offline:
-    case XENPF_cpu_hotadd:
-    case XENPF_mem_hotadd:
-        return 0;
-#endif
-
-    case XENPF_settime32:
-    case XENPF_settime64:
-        return domain_has_xen(current->domain, XEN__SETTIME);
-
-    case XENPF_add_memtype:
-        return domain_has_xen(current->domain, XEN__MTRR_ADD);
-
-    case XENPF_del_memtype:
-        return domain_has_xen(current->domain, XEN__MTRR_DEL);
-
-    case XENPF_read_memtype:
-        return domain_has_xen(current->domain, XEN__MTRR_READ);
-
-    case XENPF_microcode_update:
-        return domain_has_xen(current->domain, XEN__MICROCODE);
-
-    case XENPF_platform_quirk:
-        return domain_has_xen(current->domain, XEN__QUIRK);
-
-    case XENPF_firmware_info:
-        return domain_has_xen(current->domain, XEN__FIRMWARE);
-
-    case XENPF_efi_runtime_call:
-        return domain_has_xen(current->domain, XEN__FIRMWARE);
-
-    case XENPF_enter_acpi_sleep:
-        return domain_has_xen(current->domain, XEN__SLEEP);
-
-    case XENPF_change_freq:
-        return domain_has_xen(current->domain, XEN__FREQUENCY);
-
-    case XENPF_getidletime:
-        return domain_has_xen(current->domain, XEN__GETIDLE);
-
-    case XENPF_set_processor_pminfo:
-    case XENPF_core_parking:
-        return domain_has_xen(current->domain, XEN__PM_OP);
-
-    case XENPF_get_cpu_version:
-    case XENPF_get_cpuinfo:
-        return domain_has_xen(current->domain, XEN__GETCPUINFO);
-
-    case XENPF_resource_op:
-        return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2,
-                                    XEN2__RESOURCE_OP, NULL);
-
-    case XENPF_get_symbol:
-        return avc_has_perm(domain_sid(current->domain), SECINITSID_XEN,
-                            SECCLASS_XEN2, XEN2__GET_SYMBOL, NULL);
-
-    default:
-        printk("flask_platform_op: Unknown op %d\n", op);
-        return -EPERM;
-    }
-}
-
 static int flask_machine_memory_map(void)
 {
     return avc_current_has_perm(SECINITSID_XEN, SECCLASS_MMU, MMU__MEMORYMAP, NULL);
@@ -1738,6 +1738,7 @@ static struct xsm_operations flask_ops = {
     .deassign_dtdevice = flask_deassign_dtdevice,
 #endif
 
+    .platform_op = flask_platform_op,
 #ifdef CONFIG_X86
     .do_mca = flask_do_mca,
     .shadow_control = flask_shadow_control,
@@ -1748,7 +1749,6 @@ static struct xsm_operations flask_ops = {
     .hvm_ioreq_server = flask_hvm_ioreq_server,
     .mem_sharing_op = flask_mem_sharing_op,
     .apic = flask_apic,
-    .platform_op = flask_platform_op,
     .machine_memory_map = flask_machine_memory_map,
     .domain_memory_map = flask_domain_memory_map,
     .mmu_update = flask_mmu_update,