74 lines
2.0 KiB
C
Executable File
74 lines
2.0 KiB
C
Executable File
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2023 MediaTek Inc.
|
|
*/
|
|
#include <linux/clocksource.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/timekeeping.h>
|
|
#include <linux/soc/mediatek/gzvm_drv.h>
|
|
#include "gzvm_arch_common.h"
|
|
|
|
#define GZVM_PTP_VIRT_COUNTER 0
|
|
#define GZVM_PTP_PHYS_COUNTER 1
|
|
/**
|
|
* gzvm_handle_ptp_time() - Sync time between host and guest VM
|
|
* @vcpu: Pointer to struct gzvm_vcpu_run in userspace
|
|
* @counter: Counter type from guest VM
|
|
* Return: Always return 0 because there are no cases of failure
|
|
*
|
|
* The following register values will be passed to the guest VM
|
|
* for time synchronization:
|
|
* regs->x0 (upper 32 bits) wall clock time
|
|
* regs->x1 (lower 32 bits) wall clock time
|
|
* regs->x2 (upper 32 bits) cycles
|
|
* regs->x3 (lower 32 bits) cycles
|
|
*/
|
|
static int gzvm_handle_ptp_time(struct gzvm_vcpu *vcpu, int counter)
|
|
{
|
|
struct system_time_snapshot snapshot;
|
|
u64 cycles = 0;
|
|
|
|
ktime_get_snapshot(&snapshot);
|
|
|
|
switch (counter) {
|
|
case GZVM_PTP_VIRT_COUNTER:
|
|
cycles = snapshot.cycles -
|
|
le64_to_cpu(vcpu->hwstate->vtimer_offset);
|
|
break;
|
|
case GZVM_PTP_PHYS_COUNTER:
|
|
cycles = snapshot.cycles;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
vcpu->run->hypercall.args[0] = upper_32_bits(snapshot.real);
|
|
vcpu->run->hypercall.args[1] = lower_32_bits(snapshot.real);
|
|
vcpu->run->hypercall.args[2] = upper_32_bits(cycles);
|
|
vcpu->run->hypercall.args[3] = lower_32_bits(cycles);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* gzvm_arch_handle_guest_hvc() - Handle architecture-related guest hvc
|
|
* @vcpu: Pointer to struct gzvm_vcpu_run in userspace
|
|
* Return:
|
|
* * true - This hvc has been processed, no need to back to VMM.
|
|
* * false - This hvc has not been processed, require userspace.
|
|
*/
|
|
bool gzvm_arch_handle_guest_hvc(struct gzvm_vcpu *vcpu)
|
|
{
|
|
int ret, counter;
|
|
|
|
switch (vcpu->run->hypercall.args[0]) {
|
|
case GZVM_HVC_PTP:
|
|
counter = vcpu->run->hypercall.args[1];
|
|
ret = gzvm_handle_ptp_time(vcpu, counter);
|
|
return (ret == 0) ? true : false;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|