diff options
author | Christoffer Dall <christoffer.dall@linaro.org> | 2013-09-23 17:55:56 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2013-12-21 13:01:22 -0500 |
commit | ce01e4e8874d410738f4b4733b26642d6611a331 (patch) | |
tree | f58e80efb4fc588858f4c16e48dec45659cb5048 /virt/kvm/arm/vgic.c | |
parent | 7330672befe6269e575f79b924a7068b26c144b4 (diff) |
KVM: arm-vgic: Set base addr through device API
Support setting the distributor and cpu interface base addresses in the
VM physical address space through the KVM_{SET,GET}_DEVICE_ATTR API
in addition to the ARM specific API.
This has the added benefit of being able to share more code in user
space and do things in a uniform manner.
Also deprecate the older API at the same time, but backwards
compatibility will be maintained.
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt/kvm/arm/vgic.c')
-rw-r--r-- | virt/kvm/arm/vgic.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index b15d6c17a090..45db48de4282 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -1495,6 +1495,12 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr, | |||
1495 | { | 1495 | { |
1496 | int ret; | 1496 | int ret; |
1497 | 1497 | ||
1498 | if (addr & ~KVM_PHYS_MASK) | ||
1499 | return -E2BIG; | ||
1500 | |||
1501 | if (addr & (SZ_4K - 1)) | ||
1502 | return -EINVAL; | ||
1503 | |||
1498 | if (!IS_VGIC_ADDR_UNDEF(*ioaddr)) | 1504 | if (!IS_VGIC_ADDR_UNDEF(*ioaddr)) |
1499 | return -EEXIST; | 1505 | return -EEXIST; |
1500 | if (addr + size < addr) | 1506 | if (addr + size < addr) |
@@ -1507,26 +1513,41 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr, | |||
1507 | return ret; | 1513 | return ret; |
1508 | } | 1514 | } |
1509 | 1515 | ||
1510 | int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr) | 1516 | /** |
1517 | * kvm_vgic_addr - set or get vgic VM base addresses | ||
1518 | * @kvm: pointer to the vm struct | ||
1519 | * @type: the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX | ||
1520 | * @addr: pointer to address value | ||
1521 | * @write: if true set the address in the VM address space, if false read the | ||
1522 | * address | ||
1523 | * | ||
1524 | * Set or get the vgic base addresses for the distributor and the virtual CPU | ||
1525 | * interface in the VM physical address space. These addresses are properties | ||
1526 | * of the emulated core/SoC and therefore user space initially knows this | ||
1527 | * information. | ||
1528 | */ | ||
1529 | int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) | ||
1511 | { | 1530 | { |
1512 | int r = 0; | 1531 | int r = 0; |
1513 | struct vgic_dist *vgic = &kvm->arch.vgic; | 1532 | struct vgic_dist *vgic = &kvm->arch.vgic; |
1514 | 1533 | ||
1515 | if (addr & ~KVM_PHYS_MASK) | ||
1516 | return -E2BIG; | ||
1517 | |||
1518 | if (addr & (SZ_4K - 1)) | ||
1519 | return -EINVAL; | ||
1520 | |||
1521 | mutex_lock(&kvm->lock); | 1534 | mutex_lock(&kvm->lock); |
1522 | switch (type) { | 1535 | switch (type) { |
1523 | case KVM_VGIC_V2_ADDR_TYPE_DIST: | 1536 | case KVM_VGIC_V2_ADDR_TYPE_DIST: |
1524 | r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base, | 1537 | if (write) { |
1525 | addr, KVM_VGIC_V2_DIST_SIZE); | 1538 | r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base, |
1539 | *addr, KVM_VGIC_V2_DIST_SIZE); | ||
1540 | } else { | ||
1541 | *addr = vgic->vgic_dist_base; | ||
1542 | } | ||
1526 | break; | 1543 | break; |
1527 | case KVM_VGIC_V2_ADDR_TYPE_CPU: | 1544 | case KVM_VGIC_V2_ADDR_TYPE_CPU: |
1528 | r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base, | 1545 | if (write) { |
1529 | addr, KVM_VGIC_V2_CPU_SIZE); | 1546 | r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base, |
1547 | *addr, KVM_VGIC_V2_CPU_SIZE); | ||
1548 | } else { | ||
1549 | *addr = vgic->vgic_cpu_base; | ||
1550 | } | ||
1530 | break; | 1551 | break; |
1531 | default: | 1552 | default: |
1532 | r = -ENODEV; | 1553 | r = -ENODEV; |
@@ -1538,16 +1559,58 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr) | |||
1538 | 1559 | ||
1539 | static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | 1560 | static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) |
1540 | { | 1561 | { |
1562 | int r; | ||
1563 | |||
1564 | switch (attr->group) { | ||
1565 | case KVM_DEV_ARM_VGIC_GRP_ADDR: { | ||
1566 | u64 __user *uaddr = (u64 __user *)(long)attr->addr; | ||
1567 | u64 addr; | ||
1568 | unsigned long type = (unsigned long)attr->attr; | ||
1569 | |||
1570 | if (copy_from_user(&addr, uaddr, sizeof(addr))) | ||
1571 | return -EFAULT; | ||
1572 | |||
1573 | r = kvm_vgic_addr(dev->kvm, type, &addr, true); | ||
1574 | return (r == -ENODEV) ? -ENXIO : r; | ||
1575 | } | ||
1576 | } | ||
1577 | |||
1541 | return -ENXIO; | 1578 | return -ENXIO; |
1542 | } | 1579 | } |
1543 | 1580 | ||
1544 | static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | 1581 | static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) |
1545 | { | 1582 | { |
1546 | return -ENXIO; | 1583 | int r = -ENXIO; |
1584 | |||
1585 | switch (attr->group) { | ||
1586 | case KVM_DEV_ARM_VGIC_GRP_ADDR: { | ||
1587 | u64 __user *uaddr = (u64 __user *)(long)attr->addr; | ||
1588 | u64 addr; | ||
1589 | unsigned long type = (unsigned long)attr->attr; | ||
1590 | |||
1591 | r = kvm_vgic_addr(dev->kvm, type, &addr, false); | ||
1592 | if (r) | ||
1593 | return (r == -ENODEV) ? -ENXIO : r; | ||
1594 | |||
1595 | if (copy_to_user(uaddr, &addr, sizeof(addr))) | ||
1596 | return -EFAULT; | ||
1597 | } | ||
1598 | } | ||
1599 | |||
1600 | return r; | ||
1547 | } | 1601 | } |
1548 | 1602 | ||
1549 | static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | 1603 | static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) |
1550 | { | 1604 | { |
1605 | switch (attr->group) { | ||
1606 | case KVM_DEV_ARM_VGIC_GRP_ADDR: | ||
1607 | switch (attr->attr) { | ||
1608 | case KVM_VGIC_V2_ADDR_TYPE_DIST: | ||
1609 | case KVM_VGIC_V2_ADDR_TYPE_CPU: | ||
1610 | return 0; | ||
1611 | } | ||
1612 | break; | ||
1613 | } | ||
1551 | return -ENXIO; | 1614 | return -ENXIO; |
1552 | } | 1615 | } |
1553 | 1616 | ||