(__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
 #define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
 
+/* PL1 Physical Timer Registers */
+#define KVM_REG_ARM_PTIMER_CTL         ARM_CP15_REG32(0, 14, 2, 1)
+#define KVM_REG_ARM_PTIMER_CNT         ARM_CP15_REG64(0, 14)
+#define KVM_REG_ARM_PTIMER_CVAL                ARM_CP15_REG64(2, 14)
+
+/* Virtual Timer Registers */
 #define KVM_REG_ARM_TIMER_CTL          ARM_CP15_REG32(0, 14, 3, 1)
 #define KVM_REG_ARM_TIMER_CNT          ARM_CP15_REG64(1, 14)
 #define KVM_REG_ARM_TIMER_CVAL         ARM_CP15_REG64(3, 14)
 
 
 #define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
 
+/* Physical Timer EL0 Registers */
+#define KVM_REG_ARM_PTIMER_CTL         ARM64_SYS_REG(3, 3, 14, 2, 1)
+#define KVM_REG_ARM_PTIMER_CVAL                ARM64_SYS_REG(3, 3, 14, 2, 2)
+#define KVM_REG_ARM_PTIMER_CNT         ARM64_SYS_REG(3, 3, 14, 0, 1)
+
+/* EL0 Virtual Timer Registers */
 #define KVM_REG_ARM_TIMER_CTL          ARM64_SYS_REG(3, 3, 14, 3, 1)
 #define KVM_REG_ARM_TIMER_CNT          ARM64_SYS_REG(3, 3, 14, 3, 2)
 #define KVM_REG_ARM_TIMER_CVAL         ARM64_SYS_REG(3, 3, 14, 0, 2)
 
 int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
 {
        struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
 
        switch (regid) {
        case KVM_REG_ARM_TIMER_CTL:
-               vtimer->cnt_ctl = value;
+               vtimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
                break;
        case KVM_REG_ARM_TIMER_CNT:
                update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
        case KVM_REG_ARM_TIMER_CVAL:
                vtimer->cnt_cval = value;
                break;
+       case KVM_REG_ARM_PTIMER_CTL:
+               ptimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
+               break;
+       case KVM_REG_ARM_PTIMER_CVAL:
+               ptimer->cnt_cval = value;
+               break;
+
        default:
                return -1;
        }
        return 0;
 }
 
+static u64 read_timer_ctl(struct arch_timer_context *timer)
+{
+       /*
+        * Set ISTATUS bit if it's expired.
+        * Note that according to ARMv8 ARM Issue A.k, ISTATUS bit is
+        * UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit
+        * regardless of ENABLE bit for our implementation convenience.
+        */
+       if (!kvm_timer_compute_delta(timer))
+               return timer->cnt_ctl | ARCH_TIMER_CTRL_IT_STAT;
+       else
+               return timer->cnt_ctl;
+}
+
 u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
 {
+       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
        struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
 
        switch (regid) {
        case KVM_REG_ARM_TIMER_CTL:
-               return vtimer->cnt_ctl;
+               return read_timer_ctl(vtimer);
        case KVM_REG_ARM_TIMER_CNT:
                return kvm_phys_timer_read() - vtimer->cntvoff;
        case KVM_REG_ARM_TIMER_CVAL:
                return vtimer->cnt_cval;
+       case KVM_REG_ARM_PTIMER_CTL:
+               return read_timer_ctl(ptimer);
+       case KVM_REG_ARM_PTIMER_CVAL:
+               return ptimer->cnt_cval;
+       case KVM_REG_ARM_PTIMER_CNT:
+               return kvm_phys_timer_read();
        }
        return (u64)-1;
 }