From 8290927257600951622d416c9e76ab9042c4d47d Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 5 Aug 2014 11:10:54 +0100 Subject: [PATCH] xen: arm: support platform_hypercalls for XENPF_settime Very WIP. Needs proper refactoring of x86 stuff etc. Signed-off-by: Ian Campbell --- xen/arch/arm/Makefile | 1 + xen/arch/arm/domain.c | 4 +++ xen/arch/arm/time.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++- xen/arch/arm/traps.c | 1 + xen/include/xsm/dummy.h | 12 ++++----- xen/include/xsm/xsm.h | 13 +++++----- 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index c13206f..f08187e 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -34,6 +34,7 @@ obj-y += hvm.o obj-y += device.o obj-y += decode.o obj-y += processor.o +obj-y += platform_hypercall.o #obj-bin-y += ....o diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 2b53931..a48adfc 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -630,6 +630,7 @@ static int is_guest_pv64_psr(uint32_t psr) int arch_set_info_guest( struct vcpu *v, vcpu_guest_context_u c) { + struct domain *d = v->domain; struct vcpu_guest_context *ctxt = c.nat; struct vcpu_guest_core_regs *regs = &c.nat->user_regs; @@ -667,6 +668,9 @@ int arch_set_info_guest( v->arch.ttbr1 = ctxt->ttbr1; v->arch.ttbcr = ctxt->ttbcr; + if ( v->vcpu_id == 0 ) + update_domain_wallclock_time(d); + v->is_initialised = 1; if ( ctxt->flags & VGCF_online ) diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index a6436f1..e271530 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -35,6 +35,7 @@ #include #include #include +#include uint64_t __read_mostly boot_count; @@ -217,13 +218,73 @@ void update_vcpu_system_time(struct vcpu *v) void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds) { + printk("dom%d time offset %"PRId32"\n", d->domain_id, time_offset_seconds); d->time_offset_seconds = time_offset_seconds; /* XXX update guest visible wallclock time */ } +static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */ +static DEFINE_SPINLOCK(wc_lock); + +/* Explicitly OR with 1 just in case version number gets out of sync. */ +#define version_update_begin(v) (((v)+1)|1) +#define version_update_end(v) ((v)+1) + +void update_domain_wallclock_time(struct domain *d) +{ + uint32_t *wc_version; + + spin_lock(&wc_lock); + + wc_version = &shared_info(d, wc_version); + *wc_version = version_update_begin(*wc_version); + wmb(); + + shared_info(d, wc_sec) = wc_sec + d->time_offset_seconds; + shared_info(d, wc_nsec) = wc_nsec; + + wmb(); + *wc_version = version_update_end(*wc_version); + + spin_unlock(&wc_lock); +} + +/* Set clock to after 00:00:00 UTC, 1 January, 1970. */ +/* XXX refactor x86 */ +void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base) +{ + u64 x; + u32 y; + struct domain *d; + + x = SECONDS(secs) + (u64)nsecs - system_time_base; + y = do_div(x, 1000000000); + + spin_lock(&wc_lock); + wc_sec = x; + wc_nsec = y; + spin_unlock(&wc_lock); + + rcu_read_lock(&domlist_read_lock); + for_each_domain ( d ) + update_domain_wallclock_time(d); + rcu_read_unlock(&domlist_read_lock); +} + struct tm wallclock_time(uint64_t *ns) { - return (struct tm) { 0 }; + uint64_t seconds, nsec; + + if ( !wc_sec ) + return (struct tm) { 0 }; + + seconds = NOW() + SECONDS(wc_sec) + wc_nsec; + nsec = do_div(seconds, 1000000000); + + if ( ns ) + *ns = nsec; + + return gmtime(seconds); } /* diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 76a9586..227b4e2 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1035,6 +1035,7 @@ static arm_hypercall_t arm_hypercall_table[] = { HYPERCALL(grant_table_op, 3), HYPERCALL(multicall, 2), HYPERCALL_ARM(vcpu_op, 3), + HYPERCALL(platform_op, 1), }; typedef int (*arm_psci_fn_t)(uint32_t, register_t); diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index c5aa316..2cc145c 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -507,6 +507,12 @@ static XSM_INLINE int xsm_hvm_param_nested(XSM_DEFAULT_ARG struct domain *d) return xsm_default_action(action, current->domain, d); } +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) { @@ -574,12 +580,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); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index a85045d..7752b37 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -140,6 +140,8 @@ struct xsm_operations { int (*hvm_control) (struct domain *d, unsigned long op); int (*hvm_param_nested) (struct domain *d); + int (*platform_op) (uint32_t cmd); + #ifdef CONFIG_X86 int (*do_mca) (void); int (*shadow_control) (struct domain *d, uint32_t op); @@ -153,7 +155,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 @@ -534,6 +535,11 @@ static inline int xsm_hvm_param_nested (xsm_default_t def, struct domain *d) return xsm_ops->hvm_param_nested(d); } +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) { @@ -595,11 +601,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(); -- 1.7.10.4