Skip to content

Commit

Permalink
Merge branch 'kvm-arm/timer' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/maz/arm-platforms into next/virt

From Marc Zyngier, this branch enables virtual GIC and timer for KVM/ARM.

* 'kvm-arm/timer' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms:
  ARM: KVM: arch_timers: Wire the init code and config option
  ARM: KVM: arch_timers: Add timer world switch
  ARM: KVM: arch_timers: Add guest timer core support
  ARM: KVM: Add VGIC configuration option
  ARM: KVM: VGIC initialisation code
  ARM: KVM: VGIC control interface world switch
  ARM: KVM: VGIC interrupt injection
  ARM: KVM: vgic: retire queued, disabled interrupts
  ARM: KVM: VGIC virtual CPU interface management
  ARM: KVM: VGIC distributor handling
  ARM: KVM: VGIC accept vcpu and dist base addresses from user space
  ARM: KVM: Initial VGIC infrastructure code
  ARM: KVM: Keep track of currently running vcpus
  KVM: ARM: Introduce KVM_ARM_SET_DEVICE_ADDR ioctl
  ARM: gic: add __ASSEMBLY__ guard to C definitions
  ARM: gic: define GICH offsets for VGIC support
  ARM: gic: add missing distributor defintions
  • Loading branch information
Olof Johansson committed Feb 12, 2013
2 parents 0582b05 + 967f842 commit b221498
Show file tree
Hide file tree
Showing 18 changed files with 2,581 additions and 14 deletions.
38 changes: 38 additions & 0 deletions Documentation/virtual/kvm/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,44 @@ This ioctl returns the guest registers that are supported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.


4.80 KVM_ARM_SET_DEVICE_ADDR

Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
Architectures: arm
Type: vm ioctl
Parameters: struct kvm_arm_device_address (in)
Returns: 0 on success, -1 on error
Errors:
ENODEV: The device id is unknown
ENXIO: Device not supported on current system
EEXIST: Address already set
E2BIG: Address outside guest physical address space
EBUSY: Address overlaps with other device range

struct kvm_arm_device_addr {
__u64 id;
__u64 addr;
};

Specify a device address in the guest's physical address space where guests
can access emulated or directly exposed devices, which the host kernel needs
to know about. The id field is an architecture specific identifier for a
specific device.

ARM divides the id field into two parts, a device id and an address type id
specific to the individual device.

 bits: | 63 ... 32 | 31 ... 16 | 15 ... 0 |
field: | 0x00000000 | device id | addr type id |

ARM currently only require this when using the in-kernel GIC support for the
hardware VGIC features, using KVM_ARM_DEVICE_VGIC_V2 as the device id. When
setting the base address for the guest's mapping of the VGIC virtual CPU
and distributor interface, the ioctl must be called after calling
KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
this ioctl twice for any of the base addresses will return -EEXIST.


5. The kvm_run structure
------------------------

Expand Down
85 changes: 85 additions & 0 deletions arch/arm/include/asm/kvm_arch_timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2012 ARM Ltd.
* Author: Marc Zyngier <marc.zyngier@arm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifndef __ASM_ARM_KVM_ARCH_TIMER_H
#define __ASM_ARM_KVM_ARCH_TIMER_H

#include <linux/clocksource.h>
#include <linux/hrtimer.h>
#include <linux/workqueue.h>

struct arch_timer_kvm {
#ifdef CONFIG_KVM_ARM_TIMER
/* Is the timer enabled */
bool enabled;

/* Virtual offset */
cycle_t cntvoff;
#endif
};

struct arch_timer_cpu {
#ifdef CONFIG_KVM_ARM_TIMER
/* Registers: control register, timer value */
u32 cntv_ctl; /* Saved/restored */
cycle_t cntv_cval; /* Saved/restored */

/*
* Anything that is not used directly from assembly code goes
* here.
*/

/* Background timer used when the guest is not running */
struct hrtimer timer;

/* Work queued with the above timer expires */
struct work_struct expired;

/* Background timer active */
bool armed;

/* Timer IRQ */
const struct kvm_irq_level *irq;
#endif
};

#ifdef CONFIG_KVM_ARM_TIMER
int kvm_timer_hyp_init(void);
int kvm_timer_init(struct kvm *kvm);
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu);
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu);
void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu);
#else
static inline int kvm_timer_hyp_init(void)
{
return 0;
};

static inline int kvm_timer_init(struct kvm *kvm)
{
return 0;
}

static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {}
static inline void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) {}
static inline void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) {}
static inline void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) {}
#endif

#endif
3 changes: 2 additions & 1 deletion arch/arm/include/asm/kvm_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
#define c13_TID_URW 23 /* Thread ID, User R/W */
#define c13_TID_URO 24 /* Thread ID, User R/O */
#define c13_TID_PRIV 25 /* Thread ID, Privileged */
#define NR_CP15_REGS 26 /* Number of regs (incl. invalid) */
#define c14_CNTKCTL 26 /* Timer Control Register (PL1) */
#define NR_CP15_REGS 27 /* Number of regs (incl. invalid) */

#define ARM_EXCEPTION_RESET 0
#define ARM_EXCEPTION_UNDEFINED 1
Expand Down
23 changes: 23 additions & 0 deletions arch/arm/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_mmio.h>
#include <asm/fpstate.h>
#include <asm/kvm_arch_timer.h>

#define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
#define KVM_MEMORY_SLOTS 32
Expand All @@ -37,6 +38,8 @@
#define KVM_NR_PAGE_SIZES 1
#define KVM_PAGES_PER_HPAGE(x) (1UL<<31)

#include <asm/kvm_vgic.h>

struct kvm_vcpu;
u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
int kvm_target_cpu(void);
Expand All @@ -47,6 +50,9 @@ struct kvm_arch {
/* VTTBR value associated with below pgd and vmid */
u64 vttbr;

/* Timer */
struct arch_timer_kvm timer;

/*
* Anything that is not used directly from assembly code goes
* here.
Expand All @@ -58,6 +64,9 @@ struct kvm_arch {

/* Stage-2 page table */
pgd_t *pgd;

/* Interrupt controller */
struct vgic_dist vgic;
};

#define KVM_NR_MEM_OBJS 40
Expand Down Expand Up @@ -92,6 +101,10 @@ struct kvm_vcpu_arch {
struct vfp_hard_struct vfp_guest;
struct vfp_hard_struct *vfp_host;

/* VGIC state */
struct vgic_cpu vgic_cpu;
struct arch_timer_cpu timer_cpu;

/*
* Anything that is not used directly from assembly code goes
* here.
Expand Down Expand Up @@ -158,4 +171,14 @@ static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
{
return 0;
}

struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);

int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
struct kvm_one_reg;
int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);

#endif /* __ARM_KVM_HOST_H__ */
Loading

0 comments on commit b221498

Please sign in to comment.