Commit 3401d546 authored by Christoffer Dall's avatar Christoffer Dall Committed by Marc Zyngier

KVM: ARM: Introduce KVM_ARM_SET_DEVICE_ADDR ioctl

On ARM some bits are specific to the model being emulated for the guest and
user space needs a way to tell the kernel about those bits.  An example is mmio
device base addresses, where KVM must know the base address for a given device
to properly emulate mmio accesses within a certain address range or directly
map a device with virtualiation extensions into the guest address space.

We make this API ARM-specific as we haven't yet reached a consensus for a
generic API for all KVM architectures that will allow us to do something like
this.
Reviewed-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarChristoffer Dall <c.dall@virtualopensystems.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent a96ab039
...@@ -2210,6 +2210,43 @@ This ioctl returns the guest registers that are supported for the ...@@ -2210,6 +2210,43 @@ This ioctl returns the guest registers that are supported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. 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
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 5. The kvm_run structure
------------------------ ------------------------
......
...@@ -65,6 +65,19 @@ struct kvm_regs { ...@@ -65,6 +65,19 @@ struct kvm_regs {
#define KVM_ARM_TARGET_CORTEX_A15 0 #define KVM_ARM_TARGET_CORTEX_A15 0
#define KVM_ARM_NUM_TARGETS 1 #define KVM_ARM_NUM_TARGETS 1
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
#define KVM_ARM_DEVICE_TYPE_MASK (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
#define KVM_ARM_DEVICE_ID_SHIFT 16
#define KVM_ARM_DEVICE_ID_MASK (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
/* Supported device IDs */
#define KVM_ARM_DEVICE_VGIC_V2 0
/* Supported VGIC address types */
#define KVM_VGIC_V2_ADDR_TYPE_DIST 0
#define KVM_VGIC_V2_ADDR_TYPE_CPU 1
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */ #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
struct kvm_vcpu_init { struct kvm_vcpu_init {
......
...@@ -167,6 +167,8 @@ int kvm_dev_ioctl_check_extension(long ext) ...@@ -167,6 +167,8 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_COALESCED_MMIO: case KVM_CAP_COALESCED_MMIO:
r = KVM_COALESCED_MMIO_PAGE_OFFSET; r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break; break;
case KVM_CAP_ARM_SET_DEVICE_ADDR:
r = 1;
case KVM_CAP_NR_VCPUS: case KVM_CAP_NR_VCPUS:
r = num_online_cpus(); r = num_online_cpus();
break; break;
...@@ -827,10 +829,29 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) ...@@ -827,10 +829,29 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
return -EINVAL; return -EINVAL;
} }
static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
struct kvm_arm_device_addr *dev_addr)
{
return -ENODEV;
}
long kvm_arch_vm_ioctl(struct file *filp, long kvm_arch_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg) unsigned int ioctl, unsigned long arg)
{ {
return -EINVAL; struct kvm *kvm = filp->private_data;
void __user *argp = (void __user *)arg;
switch (ioctl) {
case KVM_ARM_SET_DEVICE_ADDR: {
struct kvm_arm_device_addr dev_addr;
if (copy_from_user(&dev_addr, argp, sizeof(dev_addr)))
return -EFAULT;
return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr);
}
default:
return -EINVAL;
}
} }
static void cpu_init_hyp_mode(void *vector) static void cpu_init_hyp_mode(void *vector)
......
...@@ -637,6 +637,7 @@ struct kvm_ppc_smmu_info { ...@@ -637,6 +637,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_PPC_BOOKE_WATCHDOG 83 #define KVM_CAP_PPC_BOOKE_WATCHDOG 83
#define KVM_CAP_PPC_HTAB_FD 84 #define KVM_CAP_PPC_HTAB_FD 84
#define KVM_CAP_ARM_PSCI 87 #define KVM_CAP_ARM_PSCI 87
#define KVM_CAP_ARM_SET_DEVICE_ADDR 88
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
...@@ -784,6 +785,11 @@ struct kvm_msi { ...@@ -784,6 +785,11 @@ struct kvm_msi {
__u8 pad[16]; __u8 pad[16];
}; };
struct kvm_arm_device_addr {
__u64 id;
__u64 addr;
};
/* /*
* ioctls for VM fds * ioctls for VM fds
*/ */
...@@ -869,6 +875,8 @@ struct kvm_s390_ucas_mapping { ...@@ -869,6 +875,8 @@ struct kvm_s390_ucas_mapping {
#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma) #define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
/* Available with KVM_CAP_PPC_HTAB_FD */ /* Available with KVM_CAP_PPC_HTAB_FD */
#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd) #define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)
/* /*
* ioctls for vcpu fds * ioctls for vcpu fds
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment