--- /dev/null
+/******************************************************************************
+ * 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;
+}
}
#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)
{
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);
.deassign_dtdevice = flask_deassign_dtdevice,
#endif
+ .platform_op = flask_platform_op,
#ifdef CONFIG_X86
.do_mca = flask_do_mca,
.shadow_control = flask_shadow_control,
.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,