Skip to content

Commit

Permalink
Merge tag 'virt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm…
Browse files Browse the repository at this point in the history
…/arm-soc

Pull ARM virtualization changes:
 "This contains parts of the ARM KVM support that have dependencies on
  other patches merged through the arm-soc tree.  In combination with
  patches coming through Russell's tree, this will finally add full
  support for the kernel based virtual machine on ARM, which has been
  awaited for some time now.

  Further, we now have a separate platform for virtual machines and qemu
  booting that is used by both Xen and KVM, separating these from the
  Versatile Express reference implementation.  Obviously, this new
  platform is multiplatform capable so it can be combined with existing
  machines in the same kernel."

* tag 'virt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (38 commits)
  ARM: arch_timer: include linux/errno.h
  arm: arch_timer: add missing inline in stub function
  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
  ARM: mach-virt: fixup machine descriptor after removal of sys_timer
  ...
  • Loading branch information
Linus Torvalds committed Feb 21, 2013
2 parents a8f3740 + fe7dc72 commit 8b5628a
Show file tree
Hide file tree
Showing 39 changed files with 3,466 additions and 878 deletions.
7 changes: 4 additions & 3 deletions Documentation/devicetree/bindings/arm/arch_timer.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
* ARM architected timer

ARM Cortex-A7 and Cortex-A15 have a per-core architected timer, which
provides per-cpu timers.
ARM cores may have a per-core architected timer, which provides per-cpu timers.

The timer is attached to a GIC to deliver its per-processor interrupts.

** Timer node properties:

- compatible : Should at least contain "arm,armv7-timer".
- compatible : Should at least contain one of
"arm,armv7-timer"
"arm,armv8-timer"

- interrupts : Interrupt list for secure, non-secure, virtual and
hypervisor timers, in that order.
Expand Down
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
6 changes: 5 additions & 1 deletion arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ config ARM
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select ARCH_HAVE_CUSTOM_GPIO_H
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_WANT_IPC_PARSE_VERSION
select BUILDTIME_EXTABLE_SORT if MMU
select CPU_PM if (SUSPEND || CPU_IDLE)
Expand Down Expand Up @@ -1112,6 +1113,8 @@ source "arch/arm/mach-versatile/Kconfig"
source "arch/arm/mach-vexpress/Kconfig"
source "arch/arm/plat-versatile/Kconfig"

source "arch/arm/mach-virt/Kconfig"

source "arch/arm/mach-vt8500/Kconfig"

source "arch/arm/mach-w90x900/Kconfig"
Expand Down Expand Up @@ -1560,9 +1563,10 @@ config HAVE_ARM_SCU
help
This option enables support for the ARM system coherency unit

config ARM_ARCH_TIMER
config HAVE_ARM_ARCH_TIMER
bool "Architected timer support"
depends on CPU_V7
select ARM_ARCH_TIMER
help
This option enables support for the ARM architected timer

Expand Down
1 change: 1 addition & 0 deletions arch/arm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ machine-$(CONFIG_ARCH_SOCFPGA) += socfpga
machine-$(CONFIG_ARCH_SPEAR13XX) += spear13xx
machine-$(CONFIG_ARCH_SPEAR3XX) += spear3xx
machine-$(CONFIG_MACH_SPEAR600) += spear6xx
machine-$(CONFIG_ARCH_VIRT) += virt
machine-$(CONFIG_ARCH_ZYNQ) += zynq
machine-$(CONFIG_ARCH_SUNXI) += sunxi

Expand Down
109 changes: 103 additions & 6 deletions arch/arm/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,115 @@
#ifndef __ASMARM_ARCH_TIMER_H
#define __ASMARM_ARCH_TIMER_H

#include <asm/barrier.h>
#include <asm/errno.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/types.h>

#include <clocksource/arm_arch_timer.h>

#ifdef CONFIG_ARM_ARCH_TIMER
int arch_timer_of_register(void);
int arch_timer_sched_clock_init(void);
struct timecounter *arch_timer_get_timecounter(void);

/*
* These register accessors are marked inline so the compiler can
* nicely work out which register we want, and chuck away the rest of
* the code. At least it does so with a recent GCC (4.6.3).
*/
static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
{
if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
break;
case ARCH_TIMER_REG_TVAL:
asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
break;
}
}

if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
break;
case ARCH_TIMER_REG_TVAL:
asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
break;
}
}

isb();
}

static inline u32 arch_timer_reg_read(const int access, const int reg)
{
u32 val = 0;

if (access == ARCH_TIMER_PHYS_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
break;
case ARCH_TIMER_REG_TVAL:
asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
break;
}
}

if (access == ARCH_TIMER_VIRT_ACCESS) {
switch (reg) {
case ARCH_TIMER_REG_CTRL:
asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
break;
case ARCH_TIMER_REG_TVAL:
asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
break;
}
}

return val;
}

static inline u32 arch_timer_get_cntfrq(void)
{
u32 val;
asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
return val;
}

static inline u64 arch_counter_get_cntpct(void)
{
u64 cval;

isb();
asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
return cval;
}

static inline u64 arch_counter_get_cntvct(void)
{
u64 cval;

isb();
asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
return cval;
}

static inline void __cpuinit arch_counter_set_user_access(void)
{
u32 cntkctl;

asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));

/* disable user access to everything */
cntkctl &= ~((3 << 8) | (7 << 0));

asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
}
#else
static inline int arch_timer_of_register(void)
{
Expand All @@ -18,11 +120,6 @@ static inline int arch_timer_sched_clock_init(void)
{
return -ENXIO;
}

static inline struct timecounter *arch_timer_get_timecounter(void)
{
return NULL;
}
#endif

#endif
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 8b5628a

Please sign in to comment.