KVM/ARM vGIC support
Subsystems (3)
v5 cover KVM/ARM vGIC support
The following series implements support for the virtual generic interrupt controller architecture for KVM/ARM.
This patch series can also be pulled from:
git://github.com/virtualopensystems/linux-kvm-arm.git
branch: kvm-arm-v15-vgic
Changes since v4:
- Large number of commenting and formatting changes
- Don't rely on the vgic_hcr default value
- Fix bug in irq_fgx expand/collapse functions
- Sanitize use of bitmaps
- Do not use elrsr when queueing an interrupt
- Deassert SGIs and SPIs that have already been queued
- Set VMCR to 0 on vcpu init
- Compute number of list registers once at init time
- Restructure bytemap/bitmap accessor functions
- Improve readability by adding accessor functions
- Define GICH_ constants in gic.h and use these in the vgic code
- Explain SGI handling in comment
- Error patch and return value fixes and cleanups
- Use defines instead of all hardcoded IRQ numbers
- Refactor level interrupt handling
- Fix several maintenace-interrupt related bugs
- Add CPU hotplug notifier
Changes since v3:
- Change struct kvm_device_addr to use 64 bits for ID field
Changes since v2:
- Get rid of hardcoded guest cpu and distributor physical addresses and instead provide the address through the KVM_SET_DEVICE_ADDRESS ioctl.
- Fix level/edge bugs
- Fix reboot bug: retire queued, disabled interrupts
---
Christoffer Dall (2):
KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
ARM: KVM: VGIC accept vcpu and dist base addresses from user space
Marc Zyngier (10):
ARM: KVM: Keep track of currently running vcpus
ARM: gic: define GICH offsets for VGIC support
ARM: KVM: Initial VGIC infrastructure code
ARM: KVM: VGIC distributor handling
ARM: KVM: VGIC virtual CPU interface management
ARM: KVM: vgic: retire queued, disabled interrupts
ARM: KVM: VGIC interrupt injection
ARM: KVM: VGIC control interface world switch
ARM: KVM: VGIC initialisation code
ARM: KVM: Add VGIC configuration option
Documentation/virtual/kvm/api.txt | 38 + arch/arm/include/asm/hardware/gic.h | 25 + arch/arm/include/asm/kvm_host.h | 18 arch/arm/include/asm/kvm_vgic.h | 220 +++++ arch/arm/include/uapi/asm/kvm.h | 16 arch/arm/kernel/asm-offsets.c | 12 arch/arm/kvm/Kconfig | 8 arch/arm/kvm/Makefile | 1 arch/arm/kvm/arm.c | 162 ++++ arch/arm/kvm/interrupts.S | 4 arch/arm/kvm/interrupts_head.S | 74 ++ arch/arm/kvm/mmio.c | 3 arch/arm/kvm/vgic.c | 1492 +++++++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 8 14 files changed, 2069 insertions(+), 12 deletions(-) create mode 100644 arch/arm/include/asm/kvm_vgic.h create mode 100644 arch/arm/kvm/vgic.c
PATCH v5 1/12 KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
On ARM (and possibly other architectures) 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 try to make this API slightly more generic than for our specific use, but so far only the VGIC uses this feature.
--- Documentation/virtual/kvm/api.txt | 37 +++++++++++++++++++++++++++++++++++++ arch/arm/include/uapi/asm/kvm.h | 13 +++++++++++++ arch/arm/kvm/arm.c | 23 ++++++++++++++++++++++- include/uapi/linux/kvm.h | 8 ++++++++ 4 files changed, 80 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +37 -0
@@ -2206,6 +2206,43 @@ This ioctl returns the guest registers that are supported for the KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. +4.80 KVM_SET_DEVICE_ADDRESS + +Capability: KVM_CAP_SET_DEVICE_ADDRESS +Architectures: arm +Type: vm ioctl +Parameters: struct kvm_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_device_address { + __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 ------------------------
arch/arm/include/uapi/asm/kvm.h +13 -0
@@ -65,6 +65,19 @@ struct kvm_regs {#define KVM_ARM_TARGET_CORTEX_A15 0#define KVM_ARM_NUM_TARGETS 1 +/* KVM_SET_DEVICE_ADDRESS ioctl id encoding */ +#define KVM_DEVICE_TYPE_SHIFT 0 +#define KVM_DEVICE_TYPE_MASK (0xffff << KVM_DEVICE_TYPE_SHIFT) +#define KVM_DEVICE_ID_SHIFT 16 +#define KVM_DEVICE_ID_MASK (0xffff << KVM_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 +struct kvm_vcpu_init {__u32 target;__u32 features[7 ];
arch/arm/kvm/arm.c +22 -1
@@ -165,6 +165,8 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_COALESCED_MMIO : r =KVM_COALESCED_MMIO_PAGE_OFFSET ;break ; +case KVM_CAP_SET_DEVICE_ADDR : + r =1 ;case KVM_CAP_NR_VCPUS : r =num_online_cpus ();break ;
@@ -805,10 +807,29 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)return -EINVAL ; } +static int kvm_vm_ioctl_set_device_address (struct kvm *kvm, +struct kvm_device_address *dev_addr) +{ +return -ENODEV ; +} +long kvm_arch_vm_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) { -return -EINVAL ; +struct kvm *kvm = filp->private_data; +void __user *argp = (void __user *)arg; + +switch (ioctl) { +case KVM_SET_DEVICE_ADDRESS : { +struct kvm_device_address dev_addr; + +if (copy_from_user (&dev_addr, argp,sizeof (dev_addr))) +return -EFAULT ; +return kvm_vm_ioctl_set_device_address (kvm, &dev_addr); + } +default : +return -EINVAL ; + } }static void cpu_init_hyp_mode (void *vector)
include/uapi/linux/kvm.h +8 -0
@@ -636,6 +636,7 @@ struct kvm_ppc_smmu_info {#define KVM_CAP_IRQFD_RESAMPLE 82#define KVM_CAP_PPC_BOOKE_WATCHDOG 83#define KVM_CAP_PPC_HTAB_FD 84 +#define KVM_CAP_SET_DEVICE_ADDR 85#ifdef KVM_CAP_IRQ_ROUTING
@@ -783,6 +784,11 @@ struct kvm_msi {__u8 pad[16 ]; }; +struct kvm_device_address { +__u64 id; +__u64 addr; +}; +/* * ioctls for VM fds */
@@ -868,6 +874,8 @@ struct kvm_s390_ucas_mapping {#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)/* Available with KVM_CAP_PPC_HTAB_FD */ #define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd) +/* Available with KVM_CAP_SET_DEVICE_ADDR */ +#define KVM_SET_DEVICE_ADDRESS _IOW(KVMIO, 0xab, struct kvm_device_address)/* * ioctls for vcpu fds
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 39 lines · Christoffer Dall
On ARM (and possibly other architectures) 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 try to make this API slightly more generic than for our specific use,
but so far only the VGIC uses this feature.Signed-off-by Christoffer Dall <[email protected]>--- Documentation/virtual/kvm/api.txt | 37 +++++++++++++++++++++++++++++++++++++ arch/arm/include/uapi/asm/kvm.h | 13 +++++++++++++ arch/arm/kvm/arm.c | 23 ++++++++++++++++++++++- include/uapi/linux/kvm.h | 8 ++++++++ 4 files changed, 80 insertions(+), 1 deletion(-)Documentation/virtual/kvm/api.txt +0
-0@@ -2206,6 +2206,43 @@ This ioctl returns the guest registers thatare supported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.+4.80
KVM_SET_DEVICE_ADDRESSDocumentation/virtual/kvm/api.txt +6
-0+ +Capability: KVM_CAP_SET_DEVICE_ADDRESS +Architectures: arm +Type: vm ioctl +Parameters: struct kvm_device_address (in) +Returns: 0 on success, -1 on error
Documentation/virtual/kvm/api.txt This ioctl returns the guest registers that are supported for the · line 2225
Quoted 10 lines
Documentation/virtual/kvm/api.txt +10
-0+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_device_address { + __u64 id; + __u64 addr; +};
What about this is really specific to addresses? Can't we set other device parameters this way?
Sort of like a device equivalent of PPC's one-reg interface.
-Scott
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 53 lines · Scott Wood
Quoted 37 lines · Christoffer Dall
On ARM (and possibly other architectures) 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 try to make this API slightly more generic than for our specific use, but so far only the VGIC uses this feature.
Signed-off-by Christoffer Dall <[email protected]>--- Documentation/virtual/kvm/api.txt | 37 +++++++++++++++++++++++++++++++++++++ arch/arm/include/uapi/asm/kvm.h | 13 +++++++++++++ arch/arm/kvm/arm.c | 23 ++++++++++++++++++++++- include/uapi/linux/kvm.h | 8 ++++++++ 4 files changed, 80 insertions(+), 1 deletion(-)Documentation/virtual/kvm/api.txt +0
-0@@ -2206,6 +2206,43 @@ This ioctl returns the guest registers that aresupported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.+4.80
KVM_SET_DEVICE_ADDRESSDocumentation/virtual/kvm/api.txt +6
-0+ +Capability: KVM_CAP_SET_DEVICE_ADDRESS +Architectures: arm +Type: vm ioctl +Parameters: struct kvm_device_address (in) +Returns: 0 on success, -1 on errorDocumentation/virtual/kvm/api.txt This ioctl returns the guest registers that are supported for the · line 2225
Quoted 10 lines
Documentation/virtual/kvm/api.txt +10
-0+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_device_address { + __u64 id; + __u64 addr; +};What about this is really specific to addresses? Can't we set other device parameters this way?
Quoted 2 lines
Sort of like a device equivalent of PPC's one-reg interface.
This has been discussed a number of times, and one or the other there is a need for userspace to tell KVM to present memory-mapped devices at a given address. It was also considered to make this specific to irqchip initialization, but irqchips are different and a lot of that code is x86-specific, so that approach was discarded.
This *could* look something like this:
struct kvm_device_param {
u64 dev_id;
u64 param_id;
u64 value;
};but that has less clear, or at least less specific, semantics.
-Christoffer
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 10 lines · Christoffer Dall
Quoted 8 lines · Scott Wood
Documentation/virtual/kvm/api.txt This ioctl returns the guest registers that are supported for the · line 2225
Quoted 4 lines · Christoffer Dall
Documentation/virtual/kvm/api.txt +4
-0+struct kvm_device_address { + __u64 id; + __u64 addr; +};What about this is really specific to addresses? Can't we set
Quoted 6 lines
other device
Quoted 4 lines
parameters this way?
Sort of like a device equivalent of PPC's one-reg interface.
This has been discussed a number of times,
Sorry, this patch was just pointed out to me today. I googled the patch title but couldn't find this discussion.
Quoted 8 lines
and one or the other there
is a need for userspace to tell KVM to present memory-mapped devices at a given address. It was also considered to make this specific to irqchip initialization, but irqchips are different and a lot of that code is x86-specific, so that approach was discarded.This *could* look something like this:
Quoted 7 lines
struct kvm_device_param { u64 dev_id; u64 param_id; u64 value; };but that has less clear, or at least less specific, semantics.
Why is it less clear? You need to have device-specific documentation for what "id" means, so why not also an enumeration of "param"s? Or just keep it as is, and rename "address" to "value". Whether "dev" and "param" are combined is orthogonal from whether it's used for non-address things.
If you leave it as "address", either we'll have it being used for non-address things regardless of the name ("Not a typewriter!"), or there'll end up being yet more unnecessary ioctls, or device-specific things will end up getting shoved into CPU interfaces such as one-reg. For example, on MPIC we need to be able to specify the version of the chip to emulate in addition to the address at which it lives.
Also, why is it documented as an "arm" interface? Shouldn't it be a generic interface, with other architectures currently not implementing any IDs? What in the kvm_arch_vm_ioctl() wrapper is arm-specific?
-Scott
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 15 lines · Scott Wood
Quoted 14 lines · Christoffer Dall
Quoted 11 lines · Scott Wood
Documentation/virtual/kvm/api.txt This ioctl returns the guest registers that are supported for the · line 2225
Quoted 4 lines · Christoffer Dall
Documentation/virtual/kvm/api.txt +4
-0+struct kvm_device_address { + __u64 id; + __u64 addr; +};What about this is really specific to addresses? Can't we set other device
parameters this way?
Quoted 9 lines
Quoted 3 lines
Quoted 2 lines
Sort of like a device equivalent of PPC's one-reg interface.
This has been discussed a number of times,
Sorry, this patch was just pointed out to me today. I googled the patch title but couldn't find this discussion.
I believe it was mainly discussed at the KVM Forum in person.
Quoted 14 lines
Quoted 14 lines
and one or the other there
is a need for userspace to tell KVM to present memory-mapped devices at a given address. It was also considered to make this specific to irqchip initialization, but irqchips are different and a lot of that code is x86-specific, so that approach was discarded.This *could* look something like this:
struct kvm_device_param { u64 dev_id; u64 param_id; u64 value; };
Quoted 7 lines
Quoted 1 line
but that has less clear, or at least less specific, semantics.
Why is it less clear? You need to have device-specific documentation for what "id" means, so why not also an enumeration of "param"s? Or just keep it as is, and rename "address" to "value". Whether "dev" and "param" are combined is orthogonal from whether it's used for non-address things.
less clear in the sense that you have to look at more code to see what it does. I'm not saying that it's too unclear, at all, I'm actually fine with it, but to make my point, we can make an ioctl that's called do_something() that takes a struct with val0, val1, val2, val3, ...
Quoted 8 lines
If you leave it as "address", either we'll have it being used for non-address things regardless of the name ("Not a typewriter!"), or there'll end up being yet more unnecessary ioctls, or device-specific things will end up getting shoved into CPU interfaces such as one-reg. For example, on MPIC we need to be able to specify the version of the chip to emulate in addition to the address at which it lives.
Quoted 4 lines
Also, why is it documented as an "arm" interface? Shouldn't it be a generic interface, with other architectures currently not implementing any IDs? What in the
kvm_arch_vm_ioctl()wrapper is arm-specific?
As I remember the argument for keeping this the point was that there were other preferred methods for other archs to do this, and that ARM was the only platform that had this explicit need, but maybe I'm making this up.
I'll let Peter and Alex respond this as well, and if they're fine with changing it to what I proposed above, then let's do that, and we can make it a non arm-specific interface.
-Christoffer
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 19 lines · Christoffer Dall
Quoted 9 lines · Scott Wood
Quoted 8 lines · Christoffer Dall
This *could* look something like this:
struct kvm_device_param { u64 dev_id; u64 param_id; u64 value; };Quoted 4 lines
Quoted 1 line
but that has less clear, or at least less specific, semantics.
Why is it less clear? You need to have device-specific
documentation for
Quoted 1 line
what "id" means, so why not also an enumeration of "param"s? Or
just keep
Quoted 1 line
it as is, and rename "address" to "value". Whether "dev" and
Quoted 8 lines
"param" are
Quoted 1 line
combined is orthogonal from whether it's used for non-address
things.
less clear in the sense that you have to look at more code to see what it does. I'm not saying that it's too unclear, at all, I'm actually fine with it, but to make my point, we can make an ioctl that's called
do_something()that takes a struct with val0, val1, val2, val3, ...
Such an IOCTL would add nothing other than trading the limited and cumbersome ioctl namespace for something structured a bit differently (which isn't such a bad thing...). A set device attribute ioctl would constrain it to "take this number and convey it to the enumerated device for the enumerated configuration purpose". There's already room for device-specific semantics since you can have multiple address types.
Regarding the dev/param split, it looks like you're doing the split anyway -- might as well make them separate struct fields rather than an architecture-specific bitfield encoding.
Quoted 13 lines
Quoted 2 lines
If you leave it as "address", either we'll have it being used for non-address things regardless of the name ("Not a typewriter!"), or
there'll
Quoted 1 line
end up being yet more unnecessary ioctls, or device-specific things
will end
Quoted 1 line
up getting shoved into CPU interfaces such as one-reg. For
example, on MPIC
Quoted 1 line
we need to be able to specify the version of the chip to emulate in
addition
Quoted 3 lines
to the address at which it lives.
Also, why is it documented as an "arm" interface? Shouldn't it be
a generic
Quoted 8 lines
Quoted 1 line
interface, with other architectures currently not implementing any
IDs?
Quoted 2 lines
What in the
kvm_arch_vm_ioctl()wrapper is arm-specific?As I remember the argument for keeping this the point was that there were other preferred methods for other archs to do this, and that ARM was the only platform that had this explicit need, but maybe I'm making this up.
Well, at least PPC has this explicit need as well. :-)
Only the toplevel mechanism would be generic; it would be up to each device to decide which (if any) configuration parameters it wants to expose through it.
-Scott
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
In reply to Christoffer DallAm 09.01.2013 um 00:49 schrieb Christoffer Dall <[email protected]>:
Quoted 67 lines · Scott Wood
Quoted 15 lines · Christoffer Dall
Quoted 14 lines
Quoted 11 lines · Scott Wood
Documentation/virtual/kvm/api.txt This ioctl returns the guest registers that are supported for the · line 2225
Quoted 4 lines · Christoffer Dall
Documentation/virtual/kvm/api.txt +4
-0+struct kvm_device_address { + __u64 id; + __u64 addr; +};What about this is really specific to addresses? Can't we set other device
parameters this way?Quoted 9 lines
Quoted 3 lines
Quoted 2 lines
Sort of like a device equivalent of PPC's one-reg interface.
This has been discussed a number of times,
Sorry, this patch was just pointed out to me today. I googled the patch title but couldn't find this discussion.
I believe it was mainly discussed at the KVM Forum in person.
Quoted 14 lines
Quoted 14 lines
and one or the other there
is a need for userspace to tell KVM to present memory-mapped devices at a given address. It was also considered to make this specific to irqchip initialization, but irqchips are different and a lot of that code is x86-specific, so that approach was discarded.This *could* look something like this:
struct kvm_device_param { u64 dev_id; u64 param_id; u64 value; };Quoted 7 lines
Quoted 1 line
but that has less clear, or at least less specific, semantics.
Why is it less clear? You need to have device-specific documentation for what "id" means, so why not also an enumeration of "param"s? Or just keep it as is, and rename "address" to "value". Whether "dev" and "param" are combined is orthogonal from whether it's used for non-address things.
less clear in the sense that you have to look at more code to see what it does. I'm not saying that it's too unclear, at all, I'm actually fine with it, but to make my point, we can make an ioctl that's called
do_something()that takes a struct with val0, val1, val2, val3, ...Quoted 8 lines
If you leave it as "address", either we'll have it being used for non-address things regardless of the name ("Not a typewriter!"), or there'll end up being yet more unnecessary ioctls, or device-specific things will end up getting shoved into CPU interfaces such as one-reg. For example, on MPIC we need to be able to specify the version of the chip to emulate in addition to the address at which it lives.
Quoted 4 lines
Also, why is it documented as an "arm" interface? Shouldn't it be a generic interface, with other architectures currently not implementing any IDs? What in the
kvm_arch_vm_ioctl()wrapper is arm-specific?
Quoted 8 lines
As I remember the argument for keeping this the point was that there were other preferred methods for other archs to do this, and that ARM was the only platform that had this explicit need, but maybe I'm making this up.
I'll let Peter and Alex respond this as well, and if they're fine with changing it to what I proposed above, then let's do that, and we can make it a non arm-specific interface.
I think we should make thus at least potentially generic. In fact, I wouldn't even mind calling it DEV_REG with the same semantics as ONE_REG, just that it also gets a unique dev id that gets created during in-kernel device creation and that it's a vm ioctl.
That way we wouldn't block our path to create two in-kernel irqchips one day.
Alex
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 4 lines · Alexander Graf
I think we should make thus at least potentially generic. In fact, I wouldn't even mind calling it
DEV_REGwith the same semantics asONE_REG, just that it also gets a unique dev id that gets created during in-kernel device creation and that it's a vm ioctl.
Well, we might want a DEV_REG, but you might as well just make ONE_REG OK as a VM ioctl, since there's no reason not to have not-per-cpu but not device registers. ONE_REG already supports dividing up the ID space so you can say which device or whatever is being used, because we had things like GIC registers in mind when we put that API together.
However, this shouldn't be DEV_REG, because this isn't actually setting state in the irqchip device, it's configuring the kernel's part of the system model [compare wiring up irq routing, which also has a custom ioctl rather than a generic one]. As such it definitely needs to happen only before the VM is actually started and not during VM execution, unlike a DEV_REG which would presumably be generally valid.
Quoted 1 line
That way we wouldn't block our path to create two in-kernel irqchips one day.
Er, SET_DEVICE_ADDRESS doesn't block us doing that; that's why it has an ID parameter.
The discussion at the KVM forum, as I recall it was basically:
(a) some other ppc irqchips also want to set the base address for where
their memory mapped registers live, so this isn't a totally ARM specific weirdness
(b) we didn't need to tangle up and delay the KVM ARM work with a vague
and unspecified desire for general configurability
-- PMM
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 11 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
I think we should make thus at least potentially generic. In fact, I wouldn't even mind calling it
DEV_REGwith the same semantics asONE_REG, just that it also gets a unique dev id that gets created during in-kernel device creation and that it's a vm ioctl.Well, we might want a
DEV_REG, but you might as well just makeONE_REGOK as a VM ioctl, since there's no reason not to have not-per-cpu but not device registers.ONE_REGalready supports dividing up the ID space so you can say which device or whatever is being used, because we had things like GIC registers in mind when we put that API together.
ONE_REG's address space today doesn't include a field for the target device, because that's already predetermined by the fd you run it on. Hence my suggestion to add it as separate field, because then we keep the id space mask-free.
Quoted 6 lines
However, this shouldn't be
DEV_REG, because this isn't actually setting state in the irqchip device, it's configuring the kernel's part of the system model [compare wiring up irq routing, which also has a custom ioctl rather than a generic one]. As such it definitely needs to happen only before the VM is actually started and not during VM execution, unlike aDEV_REGwhich would presumably be generally valid.
The same can be true for ONE_REG/SET_SREGS. On PPC we support setting the PVR (CPU type) via SREGS because ONE_REG only came later. Setting the CPU type only makes sense before you first start using a vcpu. After that point it should be forbidden.
So in a way, the irqchip memory address location is a device register, as it has all the properties that a register on that device would have. It is
* per device
* one id for one purpose
* may or may not be writable during certain times
We would also keep the gates open to get a new register id one day for a second address. Imagine an interrupt controller that splits its address mappings into "PIC base registers" and "MSI target registers", though the MSI registers logically belong to the PIC. Then the ioctl as designed here gets stuck too.
Quoted 10 lines
Quoted 2 lines
That way we wouldn't block our path to create two in-kernel irqchips one day.
Er,
SET_DEVICE_ADDRESSdoesn't block us doing that; that's why it has an ID parameter.The discussion at the KVM forum, as I recall it was basically:
(a) some other ppc irqchips also want to set the base address for where their memory mapped registers live, so this isn't a totally ARM specific weirdness
Yes.
Quoted 2 lines
(b) we didn't need to tangle up and delay the KVM ARM work with a vague and unspecified desire for general configurability
Yeah, that was the basic idea. Considering that the patch set hasn't been going in for another 2 months after that discussion indicates that this isn't too much of an issue though :).
In fact, I do recall myself pointing out that we need some padding in that ioctl to accomodate for later usages like the ones above. Then we could later rename (or copy name) it and everyone'd be happy.
Alex
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 9 lines · Alexander Graf
Quoted 6 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
I think we should make thus at least potentially generic. In fact, I wouldn't even mind calling it
DEV_REGwith the same semantics asONE_REG, just that it also gets a unique dev id that gets created during in-kernel device creation and that it's a vm ioctl.
Quoted 7 lines
Quoted 5 lines
Well, we might want a
DEV_REG, but you might as well just makeONE_REGOK as a VM ioctl, since there's no reason not to have not-per-cpu but not device registers.ONE_REGalready supports dividing up the ID space so you can say which device or whatever is being used, because we had things like GIC registers in mind when we put that API together.ONE_REG's address space today doesn't include a field for the target device,
There's 16 bits of "register group type".
Quoted 3 lines
because that's already predetermined by the fd you run it on. Hence my suggestion to add it as separate field, because then we keep the id space mask-free.
Er, it already has masks for the different parts of ID space. That's a feature, not a bug.
Quoted 12 lines
Quoted 6 lines
However, this shouldn't be
DEV_REG, because this isn't actually setting state in the irqchip device, it's configuring the kernel's part of the system model [compare wiring up irq routing, which also has a custom ioctl rather than a generic one]. As such it definitely needs to happen only before the VM is actually started and not during VM execution, unlike aDEV_REGwhich would presumably be generally valid.The same can be true for ONE_REG/SET_SREGS. On PPC we support setting the PVR (CPU type) via SREGS because
ONE_REGonly came later. Setting the CPU type only makes sense before you first start using a vcpu. After that point it should be forbidden.
Quoted 6 lines
So in a way, the irqchip memory address location is a device register, as it has all the properties that a register on that device would have. It is
* per device
* one id for one purpose
* may or may not be writable during certain times
There's a distinction between "things you need to do in machine setup" and "things you need to propagate for migration". It should be possible to do a migration by doing a complete copy of all ONE_REG (and DEV_REG if we have it) state from source to destination, so it needs to be always possible to write them.
Quoted 4 lines
We would also keep the gates open to get a new register id one day for a second address. Imagine an interrupt controller that splits its address mappings into "PIC base registers" and "MSI target registers", though the MSI registers logically belong to the PIC. Then the ioctl as designed here gets stuck too.
This is exactly what ARM's GIC has already. We have several memory regions (one for the distributor, one for the cpu interface), and map them with several calls to SET_DEVICE_ADDRESS.
Quoted 6 lines
Quoted 2 lines
(b) we didn't need to tangle up and delay the KVM ARM work with a vague and unspecified desire for general configurability
Yeah, that was the basic idea. Considering that the patch set hasn't been going in for another 2 months after that discussion indicates that this isn't too much of an issue though :).
We might get there faster if people didn't keep nitpicking the APIs at the last minute :-)
-- PMM
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 52 lines · Peter Maydell
Quoted 9 lines · Alexander Graf
Quoted 6 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
I think we should make thus at least potentially generic. In fact, I wouldn't even mind calling it
DEV_REGwith the same semantics asONE_REG, just that it also gets a unique dev id that gets created during in-kernel device creation and that it's a vm ioctl.Quoted 7 lines
Quoted 5 lines
Well, we might want a
DEV_REG, but you might as well just makeONE_REGOK as a VM ioctl, since there's no reason not to have not-per-cpu but not device registers.ONE_REGalready supports dividing up the ID space so you can say which device or whatever is being used, because we had things like GIC registers in mind when we put that API together.ONE_REG's address space today doesn't include a field for the target device,
There's 16 bits of "register group type".
Quoted 3 lines
because that's already predetermined by the fd you run it on. Hence my suggestion to add it as separate field, because then we keep the id space mask-free.
Er, it already has masks for the different parts of ID space. That's a feature, not a bug.
Quoted 12 lines
Quoted 6 lines
However, this shouldn't be
DEV_REG, because this isn't actually setting state in the irqchip device, it's configuring the kernel's part of the system model [compare wiring up irq routing, which also has a custom ioctl rather than a generic one]. As such it definitely needs to happen only before the VM is actually started and not during VM execution, unlike aDEV_REGwhich would presumably be generally valid.The same can be true for ONE_REG/SET_SREGS. On PPC we support setting the PVR (CPU type) via SREGS because
ONE_REGonly came later. Setting the CPU type only makes sense before you first start using a vcpu. After that point it should be forbidden.Quoted 6 lines
So in a way, the irqchip memory address location is a device register, as it has all the properties that a register on that device would have. It is
* per device
* one id for one purpose
* may or may not be writable during certain timesThere's a distinction between "things you need to do in machine setup" and "things you need to propagate for migration". It should be possible to do a migration by doing a complete copy of all
ONE_REG(andDEV_REGif we have it) state from source to destination, so it needs to be always possible to write them.
Quoted 16 lines
Quoted 4 lines
We would also keep the gates open to get a new register id one day for a second address. Imagine an interrupt controller that splits its address mappings into "PIC base registers" and "MSI target registers", though the MSI registers logically belong to the PIC. Then the ioctl as designed here gets stuck too.
This is exactly what ARM's GIC has already. We have several memory regions (one for the distributor, one for the cpu interface), and map them with several calls to
SET_DEVICE_ADDRESS.Quoted 6 lines
Quoted 2 lines
(b) we didn't need to tangle up and delay the KVM ARM work with a vague and unspecified desire for general configurability
Yeah, that was the basic idea. Considering that the patch set hasn't been going in for another 2 months after that discussion indicates that this isn't too much of an issue though :).
well, now it's actually going in, and it seems like this is the last issue. Let's hold our breaths here for a second and let me write up a new device attribute API and send that out, and if you guys can possibly live with it, then please consider accepting it.
-Christoffer
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
In reply to Peter MaydellQuoted 16 lines · Peter Maydell
Quoted 15 lines · Alexander Graf
Quoted 11 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
I think we should make thus at least potentially generic. In fact, I wouldn't even mind calling it
DEV_REGwith the same semantics asONE_REG, just that it also gets a unique dev id that gets created during in-kernel device creation and that it's a vm ioctl.Well, we might want a
DEV_REG, but you might as well just makeONE_REGOK as a VM ioctl, since there's no reason not to have not-per-cpu but not device registers.ONE_REGalready supports dividing up the ID space so you can say which device or whatever is being used, because we had things like GIC registers in mind when we put that API together.
Quoted 3 lines
Quoted 1 line
ONE_REG's address space today doesn't include a field for the target device,
There's 16 bits of "register group type".
That's "register group", not "device id". It's constant per id. If you have an ARM register, it will always stay an ARM register. It's not going to change. But if you reuse those bits for the device id, they are going to change, because a device id is similar to a handle that should be returned by the device create ioctl.
Quoted 7 lines
Quoted 4 lines
because that's already predetermined by the fd you run it on. Hence my suggestion to add it as separate field, because then we keep the id space mask-free.
Er, it already has masks for the different parts of ID space. That's a feature, not a bug.
All those masks are constant masks and only used to make reading the IDs easier. They never change within a single type of a register.
Quoted 20 lines
Quoted 13 lines
Quoted 7 lines
However, this shouldn't be
DEV_REG, because this isn't actually setting state in the irqchip device, it's configuring the kernel's part of the system model [compare wiring up irq routing, which also has a custom ioctl rather than a generic one]. As such it definitely needs to happen only before the VM is actually started and not during VM execution, unlike aDEV_REGwhich would presumably be generally valid.The same can be true for ONE_REG/SET_SREGS. On PPC we support setting the PVR (CPU type) via SREGS because
ONE_REGonly came later. Setting the CPU type only makes sense before you first start using a vcpu. After that point it should be forbidden.Quoted 6 lines
So in a way, the irqchip memory address location is a device register, as it has all the properties that a register on that device would have. It is
* per device
* one id for one purpose
* may or may not be writable during certain times
Quoted 5 lines
There's a distinction between "things you need to do in machine setup" and "things you need to propagate for migration". It should be possible to do a migration by doing a complete copy of all
ONE_REG(andDEV_REGif we have it) state from source to destination, so it needs to be always possible to write them.
You need to somewhere encode a list of registers you want to synchronize for migration anyways. Don't include this register in that list then.
Quoted 9 lines
Quoted 5 lines
We would also keep the gates open to get a new register id one day for a second address. Imagine an interrupt controller that splits its address mappings into "PIC base registers" and "MSI target registers", though the MSI registers logically belong to the PIC. Then the ioctl as designed here gets stuck too.
This is exactly what ARM's GIC has already. We have several memory regions (one for the distributor, one for the cpu interface), and map them with several calls to
SET_DEVICE_ADDRESS.
I see.
Quoted 10 lines
Quoted 7 lines
Quoted 3 lines
(b) we didn't need to tangle up and delay the KVM ARM work with a vague and unspecified desire for general configurability
Yeah, that was the basic idea. Considering that the patch set hasn't been going in for another 2 months after that discussion indicates that this isn't too much of an issue though :).
We might get there faster if people didn't keep nitpicking the APIs at the last minute :-)
I guess we just had too much bad experience with designing horrible APIs in the past on the PPC side ;).
Alex
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
In reply to Peter MaydellQuoted 9 lines · Peter Maydell
Quoted 6 lines · Alexander Graf
Yeah, that was the basic idea. Considering that the patch set hasn't been going
in for another 2 months after that discussion indicates that this isn't too much of
an issue though :).We might get there faster if people didn't keep nitpicking the APIs at
the
Quoted 1 line
last minute :-)
Exactly. We're trying hard to get the damned thing merged, and the permanent API churn quickly becomes a burden.
My understanding was that a consensus was reached 2 months ago. Has something fundamentally changed? Something that makes this API invalid? If not, can we please keep this one?
Thanks,
M.
Signature · 1 line
Who you jivin' with that Cosmik Debris?
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 11 lines · Marc Zyngier
Quoted 8 lines · Peter Maydell
Quoted 6 lines · Alexander Graf
Yeah, that was the basic idea. Considering that the patch set hasn't been going
in for another 2 months after that discussion indicates that this isn't too much of
an issue though :).
Quoted 6 lines
Quoted 1 line
We might get there faster if people didn't keep nitpicking the APIs at
the
Quoted 1 line
last minute :-)
Exactly. We're trying hard to get the damned thing merged, and the permanent API churn quickly becomes a burden.
As I said earlier, we have had a lot of experience in creating really bad APIs in the past.
But how about making this one specific? Call it KVM_ARM_SET_VGIC_ADDRESS, keep the rest as it is, resend it, and later we can come up with an actually generic interface.
Alex
Quoted 10 lines
My understanding was that a consensus was reached 2 months ago. Has something fundamentally changed? Something that makes this API invalid? If not, can we please keep this one?
Thanks,
M.Signature · 1 line
Who you jivin' with that Cosmik Debris?
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 10 lines · Alexander Graf
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
Yeah, that was the basic idea. Considering that the patch set hasn't been going
in for another 2 months after that discussion indicates that this
isn't
Quoted 11 lines
Quoted 9 lines
Quoted 4 lines
Quoted 2 lines
too much of
an issue though :).We might get there faster if people didn't keep nitpicking the APIs at
the
Quoted 1 line
last minute :-)
Exactly. We're trying hard to get the damned thing merged, and the permanent API churn quickly becomes a burden.
As I said earlier, we have had a lot of experience in creating really
bad
Quoted 1 line
APIs in the past.
Is this one really bad? Again, what changed in the meantime that makes you think this API is wrong?
Quoted 1 line
But how about making this one specific? Call it
KVM_ARM_SET_VGIC_ADDRESS,
Quoted 2 lines
keep the rest as it is, resend it, and later we can come up with an actually generic interface.
Let's pretend you never wrote that, shall we? ;-)
M.
Signature · 1 line
Fast, cheap, reliable. Pick two.
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 22 lines · Marc Zyngier
Quoted 10 lines · Alexander Graf
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
Yeah, that was the basic idea. Considering that the patch set hasn't been going
in for another 2 months after that discussion indicates that thisisn't
Quoted 10 lines
Quoted 9 lines
Quoted 4 lines
Quoted 2 lines
too much of
an issue though :).We might get there faster if people didn't keep nitpicking the APIs at
the
Quoted 1 line
last minute :-)
Exactly. We're trying hard to get the damned thing merged, and the permanent API churn quickly becomes a burden.
Quoted 6 lines
Quoted 1 line
As I said earlier, we have had a lot of experience in creating really
bad
Quoted 1 line
APIs in the past.
Is this one really bad? Again, what changed in the meantime that makes you think this API is wrong?
I complained about it 2 months ago already.
Quoted 6 lines
Quoted 1 line
But how about making this one specific? Call it
KVM_ARM_SET_VGIC_ADDRESS,Quoted 2 lines
keep the rest as it is, resend it, and later we can come up with an actually generic interface.
Let's pretend you never wrote that, shall we? ;-)
Why? The worst thing that happened to us so far were interfaces that looked generic and extensible and turned out not to be (see SET_SREGS in the ppc code). We have 2 options to circumvent this:
1) Commonly agree on an interface that actually is extensible and use it throughout the code
2) Create a very specific interface for a single use case, keep it implemented "forever" and as soon as we need more, implement a more generic one that goes back to 1
Since the ARM patches have been out of tree for too long, I'm happy with going route 2 until we go back to square 1.
Alex
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 39 lines · Alexander Graf
Quoted 22 lines · Marc Zyngier
Quoted 10 lines · Alexander Graf
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
Yeah, that was the basic idea. Considering that the patch set hasn't been going
in for another 2 months after that discussion indicates that thisisn't
Quoted 10 lines
Quoted 9 lines
Quoted 4 lines
Quoted 2 lines
too much of
an issue though :).We might get there faster if people didn't keep nitpicking the APIs at
the
Quoted 1 line
last minute :-)
Exactly. We're trying hard to get the damned thing merged, and the permanent API churn quickly becomes a burden.
Quoted 6 lines
Quoted 1 line
As I said earlier, we have had a lot of experience in creating really
bad
Quoted 1 line
APIs in the past.
Is this one really bad? Again, what changed in the meantime that makes you think this API is wrong?
I complained about it 2 months ago already.
Quoted 5 lines
Quoted 1 line
But how about making this one specific? Call it
KVM_ARM_SET_VGIC_ADDRESS,Quoted 2 lines
keep the rest as it is, resend it, and later we can come up with an actually generic interface.
Quoted 8 lines
Quoted 1 line
Let's pretend you never wrote that, shall we? ;-)
Why? The worst thing that happened to us so far were interfaces that looked generic and extensible and turned out not to be (see
SET_SREGSin the ppc code). We have 2 options to circumvent this:1) Commonly agree on an interface that actually is extensible and use it throughout the code
2) Create a very specific interface for a single use case, keep it implemented "forever" and as soon as we need more, implement a more generic one that goes back to 1Since the ARM patches have been out of tree for too long, I'm happy with going route 2 until we go back to square 1.
I really don't want to see that. Either we keep the API as it is, or we change it for something that is really better and used by other architectures. No point in turning it upside down if we're the only one doing it.
Oh, and as we're aiming for 3.9, it'd better be ready soon...
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Re: [PATCH v5 01/12] KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
Quoted 47 lines · Marc Zyngier
Quoted 46 lines · Alexander Graf
Quoted 22 lines · Marc Zyngier
Quoted 10 lines · Alexander Graf
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Peter Maydell
Quoted 4 lines · Alexander Graf
Yeah, that was the basic idea. Considering that the patch set hasn't been going
in for another 2 months after that discussion indicates that thisisn't
Quoted 10 lines
Quoted 9 lines
Quoted 4 lines
Quoted 2 lines
too much of
an issue though :).We might get there faster if people didn't keep nitpicking the APIs at
the
Quoted 1 line
last minute :-)
Exactly. We're trying hard to get the damned thing merged, and the permanent API churn quickly becomes a burden.
Quoted 6 lines
Quoted 1 line
As I said earlier, we have had a lot of experience in creating really
bad
Quoted 1 line
APIs in the past.
Is this one really bad? Again, what changed in the meantime that makes you think this API is wrong?
I complained about it 2 months ago already.
Quoted 6 lines
Quoted 1 line
But how about making this one specific? Call it
KVM_ARM_SET_VGIC_ADDRESS,Quoted 2 lines
keep the rest as it is, resend it, and later we can come up with an actually generic interface.
Let's pretend you never wrote that, shall we? ;-)
Why? The worst thing that happened to us so far were interfaces that looked generic and extensible and turned out not to be (see
SET_SREGSin the ppc code). We have 2 options to circumvent this:1) Commonly agree on an interface that actually is extensible and use it throughout the code
2) Create a very specific interface for a single use case, keep it implemented "forever" and as soon as we need more, implement a more generic one that goes back to 1
Quoted 9 lines
Quoted 1 line
Since the ARM patches have been out of tree for too long, I'm happy with going route 2 until we go back to square 1.
I really don't want to see that. Either we keep the API as it is, or we change it for something that is really better and used by other architectures. No point in turning it upside down if we're the only one doing it.
Oh, and as we're aiming for 3.9, it'd better be ready soon...
ok, I renamed it to KVM_ARM_SET_DEVICE_ADDR, using the same binary format, so user space tools remain compatible.
I'll be happy to help out with a more generic API, once the kvm/arm patches reach upstream.
Thanks so far!
-Christoffer
PATCH v5 2/12 ARM: KVM: Keep track of currently running vcpus
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
When an interrupt occurs for the guest, it is sometimes necessary to find out which vcpu was running at that point.
Keep track of which vcpu is being run in kvm_arch_vcpu_ioctl_run(), and allow the data to be retrieved using either:
- kvm_arm_get_running_vcpu(): returns the vcpu running at this point on the current CPU. Can only be used in a non-preemptible context.
- kvm_arm_get_running_vcpus(): returns the per-CPU variable holding the running vcpus, usable for per-CPU interrupts.
--- arch/arm/include/asm/kvm_host.h | 10 ++++++++++ arch/arm/kvm/arm.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+)
arch/arm/include/asm/kvm_host.h +10 -0
@@ -155,4 +155,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__ */
arch/arm/kvm/arm.c +30 -0
@@ -53,11 +53,38 @@ static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);static struct vfp_hard_struct __percpu *kvm_host_vfp_state;static unsigned long hyp_default_vectors; +/* Per-CPU variable containing the currently running vcpu. */ +static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); +/* The VMID used in the VTTBR */ static atomic64_t kvm_vmid_gen =ATOMIC64_INIT (1 );static u8 kvm_next_vmid;static DEFINE_SPINLOCK (kvm_vmid_lock); +static void kvm_arm_set_running_vcpu (struct kvm_vcpu *vcpu) +{ +BUG_ON (preemptible ()); +__get_cpu_var (kvm_arm_running_vcpu) = vcpu; +} + +/** +* kvm_arm_get_running_vcpu - get the vcpu running on the current CPU. +* Must be called from non-preemptible context +*/ +struct kvm_vcpu *kvm_arm_get_running_vcpu (void ) +{ +BUG_ON (preemptible ()); +return __get_cpu_var (kvm_arm_running_vcpu); +} + +/** +* kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. +*/ +struct kvm_vcpu __percpu **kvm_get_running_vcpus (void ) +{ +return &kvm_arm_running_vcpu; +} +int kvm_arch_hardware_enable (void *garbage) {return 0 ;
@@ -310,10 +337,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)cpumask_clear_cpu (cpu, &vcpu->arch.require_dcache_flush);flush_cache_all ();/* We'd really want v7_flush_dcache_all() */ } + +kvm_arm_set_running_vcpu (vcpu); }void kvm_arch_vcpu_put (struct kvm_vcpu *vcpu) { +kvm_arm_set_running_vcpu (NULL ); } int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
PATCH v5 3/12 ARM: gic: define GICH offsets for VGIC support
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
The GICH_* constants are defined by the GIC HW spec, and even though they only be used by KVM to begin with, define them generically in gic.h.
--- arch/arm/include/asm/hardware/gic.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
arch/arm/include/asm/hardware/gic.h +25 -0
@@ -32,6 +32,31 @@#define GIC_DIST_CONFIG 0xc00#define GIC_DIST_SOFTINT 0xf00 +#define GICH_HCR 0x0 +#define GICH_VTR 0x4 +#define GICH_VMCR 0x8 +#define GICH_MISR 0x10 +#define GICH_EISR0 0x20 +#define GICH_EISR1 0x24 +#define GICH_ELRSR0 0x30 +#define GICH_ELRSR1 0x34 +#define GICH_APR 0xf0 +#define GICH_LR0 0x100 + +#define GICH_HCR_EN (1 << 0) +#define GICH_HCR_UIE (1 << 1) + +#define GICH_LR_VIRTUALID (0x3ff << 0) +#define GICH_LR_PHYSID_CPUID_SHIFT (10) +#define GICH_LR_PHYSID_CPUID (7 << GICH_LR_PHYSID_CPUID_SHIFT) +#define GICH_LR_STATE (3 << 28) +#define GICH_LR_PENDING_BIT (1 << 28) +#define GICH_LR_ACTIVE_BIT (1 << 29) +#define GICH_LR_EOI (1 << 19) + +#define GICH_MISR_EOI (1 << 0) +#define GICH_MISR_U (1 << 1) +#ifndef __ASSEMBLY__#include <linux/irqdomain.h> struct device_node ;
PATCH v5 4/12 ARM: KVM: Initial VGIC infrastructure code
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
Wire the basic framework code for VGIC support and the initial in-kernel MMIO support code for the VGIC, used for the distributor emulation.
--- arch/arm/include/asm/kvm_host.h | 8 ++ arch/arm/include/asm/kvm_vgic.h | 80 ++++++++++++++++++++++ arch/arm/kvm/Makefile | 1 arch/arm/kvm/arm.c | 27 +++++++ arch/arm/kvm/interrupts.S | 4 + arch/arm/kvm/mmio.c | 3 + arch/arm/kvm/vgic.c | 144 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/kvm_vgic.h create mode 100644 arch/arm/kvm/vgic.c
arch/arm/include/asm/kvm_host.h +8 -0
@@ -37,6 +37,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 );
@@ -58,6 +60,9 @@ struct kvm_arch {/* Stage-2 page table */ pgd_t *pgd; + +/* Interrupt controller */ +struct vgic_dist vgic; };#define KVM_NR_MEM_OBJS 40
@@ -92,6 +97,9 @@ struct kvm_vcpu_arch {struct vfp_hard_struct vfp_guest;struct vfp_hard_struct *vfp_host; +/* VGIC state */ +struct vgic_cpu vgic_cpu; +/* * Anything that is not used directly from assembly code goes * here.
arch/arm/include/asm/kvm_vgic.h new file +80 -0
80 lines not on this page · raw message
arch/arm/kvm/Makefile +1 -0
@@ -19,3 +19,4 @@ kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) obj-y += kvm-arm.o init.o interrupts.o obj-y += arm.o guest.o mmu.o emulate.o reset.o obj-y += coproc.o coproc_a15.o mmio.o decode.o +obj-$(CONFIG_KVM_ARM_VGIC) += vgic.o
arch/arm/kvm/arm.c +26 -1
@@ -61,6 +61,8 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);static u8 kvm_next_vmid;static DEFINE_SPINLOCK (kvm_vmid_lock); +static bool vgic_present; +static void kvm_arm_set_running_vcpu (struct kvm_vcpu *vcpu) {BUG_ON (preemptible ());
@@ -183,6 +185,9 @@ int kvm_dev_ioctl_check_extension(long ext) {int r;switch (ext) { +case KVM_CAP_IRQCHIP : + r = vgic_present; +break ;case KVM_CAP_USER_MEMORY :case KVM_CAP_SYNC_MMU :case KVM_CAP_DESTROY_MEMORY_REGION_WORKS :
@@ -313,8 +318,16 @@ int __attribute_const__ kvm_target_cpu(void)int kvm_arch_vcpu_init (struct kvm_vcpu *vcpu) { +int ret; +/* Force users to call KVM_ARM_VCPU_INIT */ vcpu->arch.target =-1 ; + +/* Set up VGIC */ + ret =kvm_vgic_vcpu_init (vcpu); +if (ret) +return ret; +return 0 ; }
@@ -374,7 +387,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,*/ int kvm_arch_vcpu_runnable (struct kvm_vcpu *v) { -return !!v->arch.irq_lines; +return !!v->arch.irq_lines ||kvm_vgic_vcpu_pending_irq (v); }int kvm_arch_vcpu_in_guest_mode (struct kvm_vcpu *v)
@@ -665,6 +678,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)update_vttbr (vcpu->kvm); +kvm_vgic_sync_to_cpu (vcpu); +local_irq_disable ();/*
@@ -677,6 +692,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)if (ret <=0 ||need_new_vmid_gen (vcpu->kvm)) {local_irq_enable (); +kvm_vgic_sync_from_cpu (vcpu);continue ; }
@@ -715,6 +731,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)* Back from guest *************************************************************/ +kvm_vgic_sync_from_cpu (vcpu); + ret =handle_exit (vcpu, run, ret); }
@@ -994,6 +1012,13 @@ static int init_hyp_mode(void) } } +/* +* Init HYP view of VGIC +*/ + err =kvm_vgic_hyp_init (); +if (err) + goto out_free_vfp; +kvm_info ("Hyp mode initialized successfully\n" );return 0 ; out_free_vfp:
arch/arm/kvm/interrupts.S +4 -0
@@ -94,6 +94,8 @@ ENTRY(__kvm_vcpu_run) save_host_regs + restore_vgic_state + @ Store hardware CP15 state and load guest state read_cp15_state store_to_vcpu = 0 write_cp15_state read_from_vcpu = 1
@@ -187,6 +189,8 @@ after_vfp_restore: read_cp15_state store_to_vcpu = 1 write_cp15_state read_from_vcpu = 0 + save_vgic_state + restore_host_regs clrex @ Clear exclusive monitor mov r0, r1 @ Return the return code
arch/arm/kvm/mmio.c +3 -0
@@ -149,6 +149,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,if (mmio.is_write)memcpy (mmio.data,vcpu_reg (vcpu, rt), mmio.len); +if (vgic_handle_mmio (vcpu, run, &mmio)) +return 1 ; +kvm_prepare_mmio (run, &mmio);return 0 ; }
arch/arm/kvm/vgic.c new file +144 -0
144 lines not on this page · raw message
Re: [PATCH v5 04/12] ARM: KVM: Initial VGIC infrastructure code
Quoted 4 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Wire the basic framework code for VGIC support and the initial in-kernel MMIO support code for the VGIC, used for the distributor emulation.
[...]
Quoted 51 lines
arch/arm/kvm/vgic.c new file +51
-0+/** +* vgic_reg_access - access vgic register +* @mmio: pointer to the data describing the mmio access +* @reg: pointer to the virtual backing of vgic distributor data +* @offset: least significant 2 bits used for word offset +* @mode: ACCESS_ mode (see defines above) +* +* Helper to make vgic register access easier using one of the access +* modes defined for vgic register access +* (read,raz,write-ignored,setbit,clearbit,write) +*/ +static void vgic_reg_access (struct kvm_exit_mmio *mmio,u32 *reg, +phys_addr_t offset,int mode) +{ +int shift = (offset &3 ) *8 ; +u32 mask; +u32 regval; + +/* +* Any alignment fault should have been delivered to the guest +* directly (ARM ARM B3.12.7 "Prioritization of aborts"). +*/ + + mask = (~0U ) >> shift; +if (reg) { + regval = *reg; + }else { +BUG_ON (mode != (ACCESS_READ_RAZ |ACCESS_WRITE_IGNORED )); + regval =0 ; + } + +if (mmio->is_write) { +u32 data = (*((u32 *)mmio->data) & mask) << shift; +switch (ACCESS_WRITE_MASK (mode)) { +case ACCESS_WRITE_IGNORED : +return ; + +case ACCESS_WRITE_SETBIT : + regval |= data; +break ; + +case ACCESS_WRITE_CLEARBIT : + regval &= ~data; +break ; + +case ACCESS_WRITE_VALUE : + regval = (regval & ~(mask << shift)) | data; +break ; + } + *reg = regval; + }else {
arch/arm/kvm/vgic.c line 94
Quoted 10 lines
arch/arm/kvm/vgic.c new file +10
-0+switch (ACCESS_READ_MASK (mode)) { +case ACCESS_READ_RAZ : + regval =0 ; +/* fall through */ + +case ACCESS_READ_VALUE : + *((u32 *)mmio->data) = (regval >> shift) & mask; + } + } +}
As I mentioned previously, I suspect that this doesn't work with big-endian systems. Whilst that's reasonable for the moment, a comment would be useful for the unlucky soul that decides to do that work in future (or add accessors for mmio->data as I suggested before).
Will
Re: [PATCH v5 04/12] ARM: KVM: Initial VGIC infrastructure code
Quoted 66 lines · Will Deacon
Quoted 4 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Wire the basic framework code for VGIC support and the initial in-kernel MMIO support code for the VGIC, used for the distributor emulation.
[...]
Quoted 58 lines
(quoted diff) +58
-0+/** + * vgic_reg_access - access vgic register + * @mmio: pointer to the data describing the mmio access + * @reg: pointer to the virtual backing of vgic distributor data + * @offset: least significant 2 bits used for word offset + * @mode: ACCESS_ mode (see defines above) + * + * Helper to make vgic register access easier using one of the access + * modes defined for vgic register access + * (read,raz,write-ignored,setbit,clearbit,write) + */ +static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, + phys_addr_t offset, int mode) +{ + int shift = (offset & 3) * 8; + u32 mask; + u32 regval; + + /* + * Any alignment fault should have been delivered to the guest + * directly (ARM ARM B3.12.7 "Prioritization of aborts"). + */ + + mask = (~0U) >> shift; + if (reg) { + regval = *reg; + } else { + BUG_ON(mode != (ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED)); + regval = 0; + } + + if (mmio->is_write) { + u32 data = (*((u32 *)mmio->data) & mask) << shift; + switch (ACCESS_WRITE_MASK(mode)) { + case ACCESS_WRITE_IGNORED: + return; + + case ACCESS_WRITE_SETBIT: + regval |= data; + break; + + case ACCESS_WRITE_CLEARBIT: + regval &= ~data; + break; + + case ACCESS_WRITE_VALUE: + regval = (regval & ~(mask << shift)) | data; + break; + } + *reg = regval; + } else { + switch (ACCESS_READ_MASK(mode)) { + case ACCESS_READ_RAZ: + regval = 0; + /* fall through */ + + case ACCESS_READ_VALUE: + *((u32 *)mmio->data) = (regval >> shift) & mask;
Quoted 9 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ } + } +}As I mentioned previously, I suspect that this doesn't work with big-endian systems. Whilst that's reasonable for the moment, a comment would be useful for the unlucky soul that decides to do that work in future (or add accessors for
mmio->dataas I suggested before).
admittedly this really hurts my brain, but I think there's actually no problem with endianness: whatever comes in mmio->data will have native endianness and the vgic is always little-endian, so a guest would have to make sure to do its own endianness conversion before writing data, or did I get this backwards? (some nasty feeling about if the OS is compiled in another endianness than the hardware everything may break).
Anyhow, I think there's another bug in this code though. Please take a look and see if you agree:
commit 3cab2b93a6f6acd3c043e584f23b94ab8f1bbd66
Author: Christoffer Dall <[email protected]> Date: Mon Jan 14 15:55:18 2013 -0500
KVM: ARM: Limit vgic read/writes to load/store length
The vgic read/write operations did not consider ldrb/strb masks, and would therefore unintentionally overwrite parts of a register.
Consider for example a store of a single byte to a word-aligned address of one of the priority registers, that would cause the 3 most significant bytes to be overwritten with zeros.
arch/arm/kvm/vgic.c +0 -0
@@ -233,6 +233,16 @@ static void vgic_cpu_irq_clear(struct kvm_vcpu
*vcpu, int irq)
vcpu->arch.vgic_cpu.pending_shared);
}
+static u32 mmio_data_read(struct kvm_exit_mmio *mmio, u32 mask) +{
+ return *((u32 *)mmio->data) & mask;
+}
+
+static void mmio_data_write(struct kvm_exit_mmio *mmio, u32 mask, u32 value) +{
+ *((u32 *)mmio->data) = value & mask;
+}
+
/**
* vgic_reg_access - access vgic register
* @mmio: pointer to the data describing the mmio access
@@ -247,8 +257,8 @@ static void vgic_cpu_irq_clear(struct kvm_vcpu *vcpu, int irq)
static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
phys_addr_t offset, int mode)
{
- int shift = (offset & 3) * 8;
- u32 mask;
+ int word_offset = (offset & 3) * 8;
+ u32 mask = (1UL << (mmio->len * 8)) - 1;
u32 regval;
/*
@@ -256,7 +266,6 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
* directly (ARM ARM B3.12.7 "Prioritization of aborts"). */
- mask = (~0U) >> shift;
if (reg) {
regval = *reg;
} else {
@@ -265,7 +274,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
}
if (mmio->is_write) {
- u32 data = (*((u32 *)mmio->data) & mask) << shift;
+ u32 data = mmio_data_read(mmio, mask) << word_offset;
switch (ACCESS_WRITE_MASK(mode)) {
case ACCESS_WRITE_IGNORED:
return;
@@ -279,7 +288,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
break;
case ACCESS_WRITE_VALUE:
- regval = (regval & ~(mask << shift)) | data;
+ regval = (regval & ~(mask << word_offset)) | data;
break;
}
*reg = regval;
@@ -290,7 +299,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,
/* fall through */
case ACCESS_READ_VALUE:
- *((u32 *)mmio->data) = (regval >> shift) & mask;
+ mmio_data_write(mmio, mask, regval >> word_offset);
}
}
}
@@ -702,6 +711,12 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
(mmio->phys_addr + mmio->len) > (base + KVM_VGIC_V2_DIST_SIZE))
return false;
+ /* We don't support ldrd / strd or ldm / stm to the emulated vgic */
+ if (mmio->len > 4) {
+ kvm_inject_dabt(vcpu, mmio->phys_addr);
+ return true;
+ }
+
range = find_matching_range(vgic_ranges, mmio, base); if (unlikely(!range || !range->handle_mmio)) {
pr_warn("Unhandled access %d %08llx %d\n",
--
Thanks,
-Christoffer
Re: [kvmarm] [PATCH v5 04/12] ARM: KVM: Initial VGIC infrastructure code
Am 14.01.2013 um 22:08 schrieb Christoffer Dall <[email protected]>:
Quoted 76 lines · Will Deacon
Quoted 66 lines · Christoffer Dall
Quoted 4 lines
From: Marc Zyngier <[email protected]>
Wire the basic framework code for VGIC support and the initial in-kernel MMIO support code for the VGIC, used for the distributor emulation.
[...]
Quoted 58 lines
(quoted diff) +58
-0+/** + * vgic_reg_access - access vgic register + * @mmio: pointer to the data describing the mmio access + * @reg: pointer to the virtual backing of vgic distributor data + * @offset: least significant 2 bits used for word offset + * @mode: ACCESS_ mode (see defines above) + * + * Helper to make vgic register access easier using one of the access + * modes defined for vgic register access + * (read,raz,write-ignored,setbit,clearbit,write) + */ +static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, + phys_addr_t offset, int mode) +{ + int shift = (offset & 3) * 8; + u32 mask; + u32 regval; + + /* + * Any alignment fault should have been delivered to the guest + * directly (ARM ARM B3.12.7 "Prioritization of aborts"). + */ + + mask = (~0U) >> shift; + if (reg) { + regval = *reg; + } else { + BUG_ON(mode != (ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED)); + regval = 0; + } + + if (mmio->is_write) { + u32 data = (*((u32 *)mmio->data) & mask) << shift; + switch (ACCESS_WRITE_MASK(mode)) { + case ACCESS_WRITE_IGNORED: + return; + + case ACCESS_WRITE_SETBIT: + regval |= data; + break; + + case ACCESS_WRITE_CLEARBIT: + regval &= ~data; + break; + + case ACCESS_WRITE_VALUE: + regval = (regval & ~(mask << shift)) | data; + break; + } + *reg = regval; + } else { + switch (ACCESS_READ_MASK(mode)) { + case ACCESS_READ_RAZ: + regval = 0; + /* fall through */ + + case ACCESS_READ_VALUE: + *((u32 *)mmio->data) = (regval >> shift) & mask;Quoted 9 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+ } + } +}As I mentioned previously, I suspect that this doesn't work with big-endian systems. Whilst that's reasonable for the moment, a comment would be useful for the unlucky soul that decides to do that work in future (or add accessors for
mmio->dataas I suggested before).
Quoted 3 lines
admittedly this really hurts my brain, but I think there's actually no problem with endianness: whatever comes in
mmio->datawill have native endianness
IIRC we have a local endianness flag on ppc. Once you introduce big endian guests, you can just add one too and add a CAP for it. I wouldn't worry about it now though.
Alex
Quoted 121 lines
and the vgic is always little-endian, so a guest would have to make sure to do its own endianness conversion before writing data, or did I get this backwards? (some nasty feeling about if the OS is compiled in another endianness than the hardware everything may break).
Anyhow, I think there's another bug in this code though. Please take a look and see if you agree:
commit
3cab2b93a6f6acd3c043e584f23b94ab8f1bbd66Author: Christoffer Dall <[email protected]> Date: Mon Jan 14 15:55:18 2013 -0500KVM: ARM: Limit vgic read/writes to load/store length
The vgic read/write operations did not consider ldrb/strb masks, and would therefore unintentionally overwrite parts of a register.
Consider for example a store of a single byte to a word-aligned address of one of the priority registers, that would cause the 3 most significant bytes to be overwritten with zeros.
Cc Marc Zyniger <[email protected]>Cc Will Deacon <[email protected]>Signed-off-by Christoffer Dall <[email protected]>arch/arm/kvm/vgic.c +10
-0@@ -233,6 +233,16 @@ static void vgic_cpu_irq_clear(struct kvm_vcpu *vcpu, int irq) vcpu->arch.vgic_cpu.pending_shared); } +static u32 mmio_data_read (struct kvm_exit_mmio *mmio,u32 mask) +{ +return *((u32 *)mmio->data) & mask; +} + +static void mmio_data_write (struct kvm_exit_mmio *mmio,u32 mask,u32 value) +{ + *((u32 *)mmio->data) = value & mask; +} +/** * vgic_reg_access - access vgic register * @mmio: pointer to the data describing the mmio access
arch/arm/kvm/vgic.c +2
-2@@ -247,8 +257,8 @@ static void vgic_cpu_irq_clear(struct kvm_vcpu *vcpu, int irq)static void vgic_reg_access (struct kvm_exit_mmio *mmio,u32 *reg,phys_addr_t offset,int mode) { -int shift = (offset &3 ) *8 ; -u32 mask; +int word_offset = (offset &3 ) *8 ; +u32 mask = (1UL << (mmio->len *8 )) -1 ;u32 regval;/*arch/arm/kvm/vgic.c +0
-1@@ -256,7 +266,6 @@ static void vgic_reg_access(struct kvm_exit_mmio*mmio, u32 *reg, * directly (ARM ARM B3.12.7 "Prioritization of aborts"). */ - mask = (~0U ) >> shift;if (reg) { regval = *reg;} else {arch/arm/kvm/vgic.c +1
-1@@ -265,7 +274,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, }if (mmio->is_write) { -u32 data = (*((u32 *)mmio->data) & mask) << shift; +u32 data =mmio_data_read (mmio, mask) << word_offset;switch (ACCESS_WRITE_MASK (mode)) {case ACCESS_WRITE_IGNORED :return;arch/arm/kvm/vgic.c +1
-1@@ -279,7 +288,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, break;case ACCESS_WRITE_VALUE : - regval = (regval & ~(mask << shift)) | data; + regval = (regval & ~(mask << word_offset)) | data;break ; }*reg = regval;arch/arm/kvm/vgic.c +1
-1@@ -290,7 +299,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,/* fall through */ case ACCESS_READ_VALUE: - *((u32 *)mmio->data) = (regval >> shift) & mask; +mmio_data_write (mmio, mask, regval >> word_offset); } }}
arch/arm/kvm/vgic.c +6
-0@@ -702,6 +711,12 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu,struct kvm_run *run, (mmio->phys_addr + mmio->len) > (base + KVM_VGIC_V2_DIST_SIZE)) return false; +/* We don't support ldrd / strd or ldm / stm to the emulated vgic */ +if (mmio->len >4 ) { +kvm_inject_dabt (vcpu, mmio->phys_addr); +return true; + } + range =find_matching_range (vgic_ranges, mmio, base);if (unlikely (!range || !range->handle_mmio)) {pr_warn("Unhandled access %d %08llx %d\n",--
Thanks,
-Christoffer
_______________________________________________
kvmarm mailing list
kvmarm at lists.cs.columbia.edu
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
Re: [PATCH v5 04/12] ARM: KVM: Initial VGIC infrastructure code
In reply to Christoffer DallQuoted 13 lines · Christoffer Dall
Quoted 7 lines · Will Deacon
Review
Quoted 5 lines · Christoffer Dall
(quoted diff) +5
-0+ case ACCESS_READ_VALUE: + *((u32 *)mmio->data) = (regval >> shift) & mask; + } + } +}Quoted 5 lines
As I mentioned previously, I suspect that this doesn't work with big-endian systems. Whilst that's reasonable for the moment, a comment would be useful for the unlucky soul that decides to do that work in future (or add accessors for
mmio->dataas I suggested before).
Quoted 7 lines
admittedly this really hurts my brain, but I think there's actually no problem with endianness: whatever comes in
mmio->datawill have native endianness and the vgic is always little-endian, so a guest would have to make sure to do its own endianness conversion before writing data, or did I get this backwards? (some nasty feeling about if the OS is compiled in another endianness than the hardware everything may break).
No, you're right. As long as the vgic is always little-endian the access will be ok.
Sorry for the false alarm,
Will
Marc Zyngier
Acked-byRe: [PATCH v5 04/12] ARM: KVM: Initial VGIC infrastructure code
In reply to Christoffer DallQuoted 27 lines · Christoffer Dall
Quoted 5 lines · Will Deacon
As I mentioned previously, I suspect that this doesn't work with big-endian systems. Whilst that's reasonable for the moment, a comment would be useful for the unlucky soul that decides to do that work in future (or add accessors for
mmio->dataas I suggested before).admittedly this really hurts my brain, but I think there's actually no problem with endianness: whatever comes in
mmio->datawill have native endianness and the vgic is always little-endian, so a guest would have to make sure to do its own endianness conversion before writing data, or did I get this backwards? (some nasty feeling about if the OS is compiled in another endianness than the hardware everything may break).Anyhow, I think there's another bug in this code though. Please take a look and see if you agree:
commit
3cab2b93a6f6acd3c043e584f23b94ab8f1bbd66Author: Christoffer Dall <[email protected]> Date: Mon Jan 14 15:55:18 2013 -0500KVM: ARM: Limit vgic read/writes to load/store length
The vgic read/write operations did not consider ldrb/strb masks, and would therefore unintentionally overwrite parts of a register.
Quoted 7 lines
Consider for example a store of a single byte to a word-aligned address of one of the priority registers, that would cause the 3 most significant bytes to be overwritten with zeros.
Cc Marc Zyniger <[email protected]>Cc Will Deacon <[email protected]>Signed-off-by Christoffer Dall <[email protected]>
Quoted 93 lines
arch/arm/kvm/vgic.c +10
-0@@ -233,6 +233,16 @@ static void vgic_cpu_irq_clear(struct kvm_vcpu *vcpu, int irq) vcpu->arch.vgic_cpu.pending_shared); } +static u32 mmio_data_read (struct kvm_exit_mmio *mmio,u32 mask) +{ +return *((u32 *)mmio->data) & mask; +} + +static void mmio_data_write (struct kvm_exit_mmio *mmio,u32 mask,u32 value) +{ + *((u32 *)mmio->data) = value & mask; +} +/** * vgic_reg_access - access vgic register * @mmio: pointer to the data describing the mmio access
arch/arm/kvm/vgic.c +2
-2@@ -247,8 +257,8 @@ static void vgic_cpu_irq_clear(struct kvm_vcpu *vcpu, int irq)static void vgic_reg_access (struct kvm_exit_mmio *mmio,u32 *reg,phys_addr_t offset,int mode) { -int shift = (offset &3 ) *8 ; -u32 mask; +int word_offset = (offset &3 ) *8 ; +u32 mask = (1UL << (mmio->len *8 )) -1 ;u32 regval;arch/arm/kvm/vgic.c +0
-1/* @@ -256,7 +266,6 @@ static void vgic_reg_access(struct kvm_exit_mmio*mmio, u32 *reg, * directly (ARM ARM B3.12.7 "Prioritization of aborts"). */ - mask = (~0U ) >> shift;if (reg) { regval = *reg;arch/arm/kvm/vgic.c +1
-1}else {@@ -265,7 +274,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, }if (mmio->is_write) { -u32 data = (*((u32 *)mmio->data) & mask) << shift; +u32 data =mmio_data_read (mmio, mask) << word_offset;switch (ACCESS_WRITE_MASK (mode)) {case ACCESS_WRITE_IGNORED :arch/arm/kvm/vgic.c +1
-1return ;@@ -279,7 +288,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, break;case ACCESS_WRITE_VALUE : - regval = (regval & ~(mask << shift)) | data; + regval = (regval & ~(mask << word_offset)) | data;break ; }arch/arm/kvm/vgic.c +1
-1*reg = regval;@@ -290,7 +299,7 @@ static void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg,/* fall through */ case ACCESS_READ_VALUE: - *((u32 *)mmio->data) = (regval >> shift) & mask; +mmio_data_write (mmio, mask, regval >> word_offset); } }}
arch/arm/kvm/vgic.c +6
-0@@ -702,6 +711,12 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu,struct kvm_run *run, (mmio->phys_addr + mmio->len) > (base + KVM_VGIC_V2_DIST_SIZE)) return false; +/* We don't support ldrd / strd or ldm / stm to the emulated vgic */ +if (mmio->len >4 ) { +kvm_inject_dabt (vcpu, mmio->phys_addr); +return true; + } + range =find_matching_range (vgic_ranges, mmio, base);if (unlikely (!range || !range->handle_mmio)) {pr_warn("Unhandled access %d %08llx %d\n",
--Thanks,
-Christoffer
Signature · 1 line
Jazz is not dead. It just smells funny...
PATCH v5 5/12 ARM: KVM: VGIC accept vcpu and dist base addresses from user space
In reply to Christoffer DallUser space defines the model to emulate to a guest and should therefore decide which addresses are used for both the virtual CPU interface directly mapped in the guest physical address space and for the emulated distributor interface, which is mapped in software by the in-kernel VGIC support.
--- Documentation/virtual/kvm/api.txt | 1 + arch/arm/include/asm/kvm_vgic.h | 9 +++++ arch/arm/include/uapi/asm/kvm.h | 3 ++ arch/arm/kvm/arm.c | 14 ++++++++ arch/arm/kvm/vgic.c | 62 +++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +1 -0
@@ -2218,6 +2218,7 @@ Errors: 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_device_address { __u64 id;
arch/arm/include/asm/kvm_vgic.h +9 -0
@@ -22,6 +22,9 @@#include <asm/hardware/gic.h> struct vgic_dist { +/* Distributor and vcpu interface mapping in the guest */ +phys_addr_t vgic_dist_base; +phys_addr_t vgic_cpu_base; };struct vgic_cpu {
@@ -33,6 +36,7 @@ struct kvm_run;struct kvm_exit_mmio ;#ifdef CONFIG_KVM_ARM_VGIC +int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio);
@@ -42,6 +46,11 @@ static inline int kvm_vgic_hyp_init(void)return 0 ; } +static inline int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr) +{ +return 0 ; +} +static inline int kvm_vgic_init (struct kvm *kvm) {return 0 ;
arch/arm/include/uapi/asm/kvm.h +3 -0
@@ -78,6 +78,9 @@ struct kvm_regs {#define KVM_VGIC_V2_ADDR_TYPE_DIST 0#define KVM_VGIC_V2_ADDR_TYPE_CPU 1 +#define KVM_VGIC_V2_DIST_SIZE 0x1000 +#define KVM_VGIC_V2_CPU_SIZE 0x2000 +struct kvm_vcpu_init {__u32 target;__u32 features[7 ];
arch/arm/kvm/arm.c +13 -1
@@ -858,7 +858,19 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)static int kvm_vm_ioctl_set_device_address (struct kvm *kvm,struct kvm_device_address *dev_addr) { -return -ENODEV ; +unsigned long dev_id, type; + + dev_id = (dev_addr->id &KVM_DEVICE_ID_MASK ) >>KVM_DEVICE_ID_SHIFT ; + type = (dev_addr->id &KVM_DEVICE_TYPE_MASK ) >>KVM_DEVICE_TYPE_SHIFT ; + +switch (dev_id) { +case KVM_ARM_DEVICE_VGIC_V2 : +if (!vgic_present) +return -ENXIO ; +return kvm_vgic_set_addr (kvm, type, dev_addr->addr); +default : +return -ENODEV ; + } } long kvm_arch_vm_ioctl(struct file *filp,
arch/arm/kvm/vgic.c +62 -0
71 lines not on this page · raw message
PATCH v5 6/12 ARM: KVM: VGIC distributor handling
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
Add the GIC distributor emulation code. A number of the GIC features are simply ignored as they are not required to boot a Linux guest.
--- arch/arm/include/asm/kvm_vgic.h | 82 +++++ arch/arm/kvm/vgic.c | 593 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 674 insertions(+), 1 deletion(-)
arch/arm/include/asm/kvm_vgic.h +82 -0
@@ -19,12 +19,94 @@#ifndef __ASM_ARM_KVM_VGIC_H#define __ASM_ARM_KVM_VGIC_H +#include <linux/kernel.h> +#include <linux/kvm.h> +#include <linux/kvm_host.h> +#include <linux/irqreturn.h> +#include <linux/spinlock.h> +#include <linux/types.h> #include <asm/hardware/gic.h> +#define VGIC_NR_IRQS 128 +#define VGIC_NR_SGIS 16 +#define VGIC_NR_PPIS 16 +#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS) +#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS) +#define VGIC_MAX_CPUS KVM_MAX_VCPUS + +/* Sanity checks... */ +#if (VGIC_MAX_CPUS >8 ) +#error Invalid number of CPU interfaces +#endif + +#if (VGIC_NR_IRQS &31 ) +#error "VGIC_NR_IRQS must be a multiple of 32" +#endif + +#if (VGIC_NR_IRQS >1024 ) +#error "VGIC_NR_IRQS must be <= 1024" +#endif + +/* +* The GIC distributor registers describing interrupts have two parts: +* - 32 per-CPU interrupts (SGI + PPI) +* - a bunch of shared interrupts (SPI) +*/ +struct vgic_bitmap { +union { +u32 reg[VGIC_NR_PRIVATE_IRQS /32 ]; + DECLARE_BITMAP(reg_ul, VGIC_NR_PRIVATE_IRQS); + } percpu[VGIC_MAX_CPUS ]; +union { +u32 reg[VGIC_NR_SHARED_IRQS /32 ]; + DECLARE_BITMAP(reg_ul, VGIC_NR_SHARED_IRQS); + } shared; +}; + +struct vgic_bytemap { +u32 percpu[VGIC_MAX_CPUS ][VGIC_NR_PRIVATE_IRQS /4 ]; +u32 shared[VGIC_NR_SHARED_IRQS /4 ]; +}; +struct vgic_dist { +#ifdef CONFIG_KVM_ARM_VGIC +spinlock_t lock; + +/* Virtual control interface mapping */ +void __iomem *vctrl_base; +/* Distributor and vcpu interface mapping in the guest */ phys_addr_t vgic_dist_base;phys_addr_t vgic_cpu_base; + +/* Distributor enabled */ +u32 enabled; + +/* Interrupt enabled (one bit per IRQ) */ +struct vgic_bitmap irq_enabled; + +/* Interrupt 'pin' level */ +struct vgic_bitmap irq_state; + +/* Level-triggered interrupt in progress */ +struct vgic_bitmap irq_active; + +/* Interrupt priority. Not used yet. */ +struct vgic_bytemap irq_priority; + +/* Level/edge triggered */ +struct vgic_bitmap irq_cfg; + +/* Source CPU per SGI and target CPU */ +u8 irq_sgi_sources[VGIC_MAX_CPUS ][16 ]; + +/* Target CPU for each IRQ */ +u8 irq_spi_cpu[VGIC_NR_SHARED_IRQS ]; +struct vgic_bitmap irq_spi_target[VGIC_MAX_CPUS ]; + +/* Bitmap indicating which CPU has something pending */ +unsigned long irq_pending_on_cpu; +#endif }; struct vgic_cpu {
arch/arm/kvm/vgic.c +592 -1
623 lines not on this page · raw message
Re: [PATCH v5 06/12] ARM: KVM: VGIC distributor handling
Quoted 20 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Add the GIC distributor emulation code. A number of the GIC features are simply ignored as they are not required to boot a Linux guest.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/include/asm/kvm_vgic.h | 82 +++++ arch/arm/kvm/vgic.c | 593 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 674 insertions(+), 1 deletion(-)arch/arm/include/asm/kvm_vgic.h +0
-0@@ -19,12 +19,94 @@#ifndef __ASM_ARM_KVM_VGIC_H#define __ASM_ARM_KVM_VGIC_H
arch/arm/include/asm/kvm_vgic.h line 31
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +8
-0+#include <linux/kernel.h> +#include <linux/kvm.h> +#include <linux/kvm_host.h> +#include <linux/irqreturn.h> +#include <linux/spinlock.h> +#include <linux/types.h> #include <asm/hardware/gic.h> +#define VGIC_NR_IRQS 128 +#define VGIC_NR_SGIS 16
Now that you have this, you can use it in a few places (see also the BUG_ONs in vgic_queue_irq).
Quoted 60 lines
arch/arm/include/asm/kvm_vgic.h +56
-0+#define VGIC_NR_PPIS 16 +#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS) +#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS) +#define VGIC_MAX_CPUS KVM_MAX_VCPUS + +/* Sanity checks... */ +#if (VGIC_MAX_CPUS >8 ) +#error Invalid number of CPU interfaces +#endif + +#if (VGIC_NR_IRQS &31 ) +#error "VGIC_NR_IRQS must be a multiple of 32" +#endif + +#if (VGIC_NR_IRQS >1024 ) +#error "VGIC_NR_IRQS must be <= 1024" +#endif + +/* +* The GIC distributor registers describing interrupts have two parts: +* - 32 per-CPU interrupts (SGI + PPI) +* - a bunch of shared interrupts (SPI) +*/ +struct vgic_bitmap { +union { +u32 reg[VGIC_NR_PRIVATE_IRQS /32 ]; + DECLARE_BITMAP(reg_ul, VGIC_NR_PRIVATE_IRQS); + } percpu[VGIC_MAX_CPUS ]; +union { +u32 reg[VGIC_NR_SHARED_IRQS /32 ]; + DECLARE_BITMAP(reg_ul, VGIC_NR_SHARED_IRQS); + } shared; +}; + +struct vgic_bytemap { +u32 percpu[VGIC_MAX_CPUS ][VGIC_NR_PRIVATE_IRQS /4 ]; +u32 shared[VGIC_NR_SHARED_IRQS /4 ]; +}; +struct vgic_dist { +#ifdef CONFIG_KVM_ARM_VGIC +spinlock_t lock; + +/* Virtual control interface mapping */ +void __iomem *vctrl_base; +/* Distributor and vcpu interface mapping in the guest */ phys_addr_t vgic_dist_base;phys_addr_t vgic_cpu_base; + +/* Distributor enabled */ +u32 enabled; + +/* Interrupt enabled (one bit per IRQ) */ +struct vgic_bitmap irq_enabled; + +/* Interrupt 'pin' level */ +struct vgic_bitmap irq_state; + +/* Level-triggered interrupt in progress */
arch/arm/include/asm/kvm_vgic.h line 101
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+struct vgic_bitmap irq_active; + +/* Interrupt priority. Not used yet. */ +struct vgic_bytemap irq_priority; + +/* Level/edge triggered */ +struct vgic_bitmap irq_cfg; + +/* Source CPU per SGI and target CPU */ +u8 irq_sgi_sources[VGIC_MAX_CPUS ][16 ];
VGIC_NR_SGIS
Quoted 20 lines
arch/arm/include/asm/kvm_vgic.h +20
-0+static u32 vgic_get_target_reg (struct kvm *kvm,int irq) +{ +struct vgic_dist *dist = &kvm->arch.vgic; +struct kvm_vcpu *vcpu; +int i, c; +unsigned long *bmap; +u32 val =0 ; + + irq -=VGIC_NR_PRIVATE_IRQS ; + +kvm_for_each_vcpu (c, vcpu, kvm) { + bmap =vgic_bitmap_get_shared_map (&dist->irq_spi_target[c]); +for (i =0 ; i <GICD_IRQS_PER_ITARGETSR ; i++) +if (test_bit (irq + i, bmap)) + val |=1 << (c + i *8 ); + } + +return val; +} +
arch/arm/include/asm/kvm_vgic.h
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+static void vgic_set_target_reg (struct kvm *kvm,u32 val,int irq) +{ +struct vgic_dist *dist = &kvm->arch.vgic; +struct kvm_vcpu *vcpu; +int i, c; +unsigned long *bmap; +u32 target; + +BUG_ON (irq &3 ); +BUG_ON (irq <VGIC_NR_PRIVATE_IRQS );
This is now different to vgic_Get_target_reg, which doesn't have the BUG_ONs. Can we remove these ones too?
Quoted 21 lines
arch/arm/include/asm/kvm_vgic.h +21
-0+ irq -=VGIC_NR_PRIVATE_IRQS ; + +/* +* Pick the LSB in each byte. This ensures we target exactly +* one vcpu per IRQ. If the byte is null, assume we target +* CPU0. +*/ +for (i =0 ; i <GICD_IRQS_PER_ITARGETSR ; i++) { +int shift = i *GICD_CPUTARGETS_BITS ; + target =ffs ((val >> shift) &0xffU ); + target = target ? (target -1 ) :0 ; + dist->irq_spi_cpu[irq + i] = target; +kvm_for_each_vcpu (c, vcpu, kvm) { + bmap =vgic_bitmap_get_shared_map (&dist->irq_spi_target[c]); +if (c == target) +set_bit (irq + i, bmap); +else +clear_bit (irq + i, bmap); + } + } +}
[...]
Quoted 53 lines
static const struct
mmio_rangevgic_ranges[] = {arch/arm/include/asm/kvm_vgic.h +52
-0+ { /* CTRL, TYPER, IIDR */ + .base = 0, + .len = 12, + .handle_mmio = handle_mmio_misc, + }, + { /* IGROUPRn */ + .base = 0x80, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_raz_wi, + }, + { /* ISENABLERn */ + .base = 0x100, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_set_enable_reg, + }, + { /* ICENABLERn */ + .base = 0x180, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_clear_enable_reg, + }, + { /* ISPENDRn */ + .base = 0x200, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_set_pending_reg, + }, + { /* ICPENDRn */ + .base = 0x280, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_clear_pending_reg, + }, + { /* ISACTIVERn */ + .base = 0x300, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_raz_wi, + }, + { /* ICACTIVERn */ + .base = 0x380, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_raz_wi, + }, + { /* IPRIORITYRn */ + .base = 0x400, + .len = VGIC_NR_IRQS, + .handle_mmio = handle_mmio_priority_reg, + }, + { /* ITARGETSRn */ + .base = 0x800, + .len = VGIC_NR_IRQS, + .handle_mmio = handle_mmio_target_reg, + }, + { /* ICFGRn */ + .base = 0xC00,
arch/arm/include/asm/kvm_vgic.h
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +8
-0+ .len = VGIC_NR_IRQS / 4, + .handle_mmio = handle_mmio_cfg_reg, + }, + {/* SGIRn */ + .base = 0xF00, + .len = 4, + .handle_mmio = handle_mmio_sgi_reg, + }, {} };
You've added named definitions for these constants to the GIC header file, so please replace these immediates with those and delete the comments.
Will
Re: [PATCH v5 06/12] ARM: KVM: VGIC distributor handling
Quoted 231 lines · Will Deacon
Quoted 20 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Add the GIC distributor emulation code. A number of the GIC features are simply ignored as they are not required to boot a Linux guest.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/include/asm/kvm_vgic.h | 82 +++++ arch/arm/kvm/vgic.c | 593 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 674 insertions(+), 1 deletion(-)arch/arm/include/asm/kvm_vgic.h +0
-0@@ -19,12 +19,94 @@#ifndef __ASM_ARM_KVM_VGIC_H#define __ASM_ARM_KVM_VGIC_Harch/arm/include/asm/kvm_vgic.h line 31
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +8
-0+#include <linux/kernel.h> +#include <linux/kvm.h> +#include <linux/kvm_host.h> +#include <linux/irqreturn.h> +#include <linux/spinlock.h> +#include <linux/types.h> #include <asm/hardware/gic.h> +#define VGIC_NR_IRQS 128 +#define VGIC_NR_SGIS 16Now that you have this, you can use it in a few places (see also the
BUG_ONsinvgic_queue_irq).Quoted 60 lines
arch/arm/include/asm/kvm_vgic.h +56
-0+#define VGIC_NR_PPIS 16 +#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS) +#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS) +#define VGIC_MAX_CPUS KVM_MAX_VCPUS + +/* Sanity checks... */ +#if (VGIC_MAX_CPUS >8 ) +#error Invalid number of CPU interfaces +#endif + +#if (VGIC_NR_IRQS &31 ) +#error "VGIC_NR_IRQS must be a multiple of 32" +#endif + +#if (VGIC_NR_IRQS >1024 ) +#error "VGIC_NR_IRQS must be <= 1024" +#endif + +/* +* The GIC distributor registers describing interrupts have two parts: +* - 32 per-CPU interrupts (SGI + PPI) +* - a bunch of shared interrupts (SPI) +*/ +struct vgic_bitmap { +union { +u32 reg[VGIC_NR_PRIVATE_IRQS /32 ]; + DECLARE_BITMAP(reg_ul, VGIC_NR_PRIVATE_IRQS); + } percpu[VGIC_MAX_CPUS ]; +union { +u32 reg[VGIC_NR_SHARED_IRQS /32 ]; + DECLARE_BITMAP(reg_ul, VGIC_NR_SHARED_IRQS); + } shared; +}; + +struct vgic_bytemap { +u32 percpu[VGIC_MAX_CPUS ][VGIC_NR_PRIVATE_IRQS /4 ]; +u32 shared[VGIC_NR_SHARED_IRQS /4 ]; +}; +struct vgic_dist { +#ifdef CONFIG_KVM_ARM_VGIC +spinlock_t lock; + +/* Virtual control interface mapping */ +void __iomem *vctrl_base; +/* Distributor and vcpu interface mapping in the guest */ phys_addr_t vgic_dist_base;phys_addr_t vgic_cpu_base; + +/* Distributor enabled */ +u32 enabled; + +/* Interrupt enabled (one bit per IRQ) */ +struct vgic_bitmap irq_enabled; + +/* Interrupt 'pin' level */ +struct vgic_bitmap irq_state; + +/* Level-triggered interrupt in progress */ arch/arm/include/asm/kvm_vgic.h line 101
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+struct vgic_bitmap irq_active; + +/* Interrupt priority. Not used yet. */ +struct vgic_bytemap irq_priority; + +/* Level/edge triggered */ +struct vgic_bitmap irq_cfg; + +/* Source CPU per SGI and target CPU */ +u8 irq_sgi_sources[VGIC_MAX_CPUS ][16 ];
VGIC_NR_SGISQuoted 20 lines
arch/arm/include/asm/kvm_vgic.h +20
-0+static u32 vgic_get_target_reg (struct kvm *kvm,int irq) +{ +struct vgic_dist *dist = &kvm->arch.vgic; +struct kvm_vcpu *vcpu; +int i, c; +unsigned long *bmap; +u32 val =0 ; + + irq -=VGIC_NR_PRIVATE_IRQS ; + +kvm_for_each_vcpu (c, vcpu, kvm) { + bmap =vgic_bitmap_get_shared_map (&dist->irq_spi_target[c]); +for (i =0 ; i <GICD_IRQS_PER_ITARGETSR ; i++) +if (test_bit (irq + i, bmap)) + val |=1 << (c + i *8 ); + } + +return val; +} +arch/arm/include/asm/kvm_vgic.h
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+static void vgic_set_target_reg (struct kvm *kvm,u32 val,int irq) +{ +struct vgic_dist *dist = &kvm->arch.vgic; +struct kvm_vcpu *vcpu; +int i, c; +unsigned long *bmap; +u32 target; + +BUG_ON (irq &3 ); +BUG_ON (irq <VGIC_NR_PRIVATE_IRQS );This is now different to
vgic_Get_target_reg, which doesn't have theBUG_ONs. Can we remove these ones too?Quoted 21 lines
arch/arm/include/asm/kvm_vgic.h +21
-0+ irq -=VGIC_NR_PRIVATE_IRQS ; + +/* +* Pick the LSB in each byte. This ensures we target exactly +* one vcpu per IRQ. If the byte is null, assume we target +* CPU0. +*/ +for (i =0 ; i <GICD_IRQS_PER_ITARGETSR ; i++) { +int shift = i *GICD_CPUTARGETS_BITS ; + target =ffs ((val >> shift) &0xffU ); + target = target ? (target -1 ) :0 ; + dist->irq_spi_cpu[irq + i] = target; +kvm_for_each_vcpu (c, vcpu, kvm) { + bmap =vgic_bitmap_get_shared_map (&dist->irq_spi_target[c]); +if (c == target) +set_bit (irq + i, bmap); +else +clear_bit (irq + i, bmap); + } + } +}[...]
Quoted 53 lines
static const struct
mmio_rangevgic_ranges[] = {arch/arm/include/asm/kvm_vgic.h +52
-0+ { /* CTRL, TYPER, IIDR */ + .base = 0, + .len = 12, + .handle_mmio = handle_mmio_misc, + }, + { /* IGROUPRn */ + .base = 0x80, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_raz_wi, + }, + { /* ISENABLERn */ + .base = 0x100, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_set_enable_reg, + }, + { /* ICENABLERn */ + .base = 0x180, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_clear_enable_reg, + }, + { /* ISPENDRn */ + .base = 0x200, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_set_pending_reg, + }, + { /* ICPENDRn */ + .base = 0x280, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_clear_pending_reg, + }, + { /* ISACTIVERn */ + .base = 0x300, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_raz_wi, + }, + { /* ICACTIVERn */ + .base = 0x380, + .len = VGIC_NR_IRQS / 8, + .handle_mmio = handle_mmio_raz_wi, + }, + { /* IPRIORITYRn */ + .base = 0x400, + .len = VGIC_NR_IRQS, + .handle_mmio = handle_mmio_priority_reg, + }, + { /* ITARGETSRn */ + .base = 0x800, + .len = VGIC_NR_IRQS, + .handle_mmio = handle_mmio_target_reg, + }, + { /* ICFGRn */ + .base = 0xC00,arch/arm/include/asm/kvm_vgic.h
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +8
-0+ .len = VGIC_NR_IRQS / 4, + .handle_mmio = handle_mmio_cfg_reg, + }, + {/* SGIRn */ + .base = 0xF00, + .len = 4, + .handle_mmio = handle_mmio_sgi_reg, + }, {} };
Quoted 3 lines
You've added named definitions for these constants to the GIC header file, so please replace these immediates with those and delete the comments.
The following two commits should address your concerns:
commit ff4648faa6fd3342ce72e537a8068ab21d4085c8
Author: Christoffer Dall <[email protected]> Date: Mon Jan 14 16:53:21 2013 -0500
KVM: ARM: vgic: Use defines instead of hardcoded numbers.
Address reviewer comments.
arch/arm/include/asm/kvm_vgic.h +1 -1
@@ -99,7 +99,7 @@ struct vgic_dist {struct vgic_bitmap irq_cfg;/* Source CPU per SGI and target CPU */ -u8 irq_sgi_sources[VGIC_MAX_CPUS ][16 ]; +u8 irq_sgi_sources[VGIC_MAX_CPUS ][VGIC_NR_SGIS ];/* Target CPU for each IRQ */ u8 irq_spi_cpu[VGIC_NR_SHARED_IRQS ];
arch/arm/kvm/vgic.c +0 -0
@@ -447,9 +447,6 @@ static void vgic_set_target_reg(struct kvm *kvm,
u32 val, int irq)
unsigned long *bmap;
u32 target;
- BUG_ON(irq & 3);
- BUG_ON(irq < VGIC_NR_PRIVATE_IRQS);
-
irq -= VGIC_NR_PRIVATE_IRQS;
/*
@@ -598,63 +595,63 @@ struct mmio_range {
};
static const struct mmio_range vgic_ranges[] = {
- { /* CTRL, TYPER, IIDR */
- .base = 0,
+ {
+ .base = GIC_DIST_CTRL,
.len = 12,
.handle_mmio = handle_mmio_misc,
},
- { /* IGROUPRn */
- .base = 0x80,
+ {
+ .base = GIC_DIST_IGROUP,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_raz_wi,
},
- { /* ISENABLERn */
- .base = 0x100,
+ {
+ .base = GIC_DIST_ENABLE_SET,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_set_enable_reg,
},
- { /* ICENABLERn */
- .base = 0x180,
+ {
+ .base = GIC_DIST_ENABLE_CLEAR,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_clear_enable_reg,
},
- { /* ISPENDRn */
- .base = 0x200,
+ {
+ .base = GIC_DIST_PENDING_SET,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_set_pending_reg,
},
- { /* ICPENDRn */
- .base = 0x280,
+ {
+ .base = GIC_DIST_PENDING_CLEAR,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_clear_pending_reg,
},
- { /* ISACTIVERn */
- .base = 0x300,
+ {
+ .base = GIC_DIST_ACTIVE_SET,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_raz_wi,
},
- { /* ICACTIVERn */
- .base = 0x380,
+ {
+ .base = GIC_DIST_ACTIVE_CLEAR,
.len = VGIC_NR_IRQS / 8,
.handle_mmio = handle_mmio_raz_wi,
},
- { /* IPRIORITYRn */
- .base = 0x400,
+ {
+ .base = GIC_DIST_PRI,
.len = VGIC_NR_IRQS,
.handle_mmio = handle_mmio_priority_reg,
},
- { /* ITARGETSRn */
- .base = 0x800,
+ {
+ .base = GIC_DIST_TARGET,
.len = VGIC_NR_IRQS,
.handle_mmio = handle_mmio_target_reg,
},
- { /* ICFGRn */
- .base = 0xC00,
+ {
+ .base = GIC_DIST_CONFIG,
.len = VGIC_NR_IRQS / 4,
.handle_mmio = handle_mmio_cfg_reg,
},
- { /* SGIRn */
- .base = 0xF00,
+ {
+ .base = GIC_DIST_SOFTINT,
.len = 4,
.handle_mmio = handle_mmio_sgi_reg,
},
@@ -856,7 +853,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
/* Sanitize the input... */
BUG_ON(sgi_source_id & ~7);
- BUG_ON(sgi_source_id && irq > 15);
+ BUG_ON(sgi_source_id && irq >= VGIC_NR_SGIS);
BUG_ON(irq >= VGIC_NR_IRQS);
kvm_debug("Queue IRQ%d\n", irq);
--
commit 940c2382e1d1cb6831d35ceeccb02c3d3f76a45c
Author: Christoffer Dall <[email protected]> Date: Mon Jan 14 16:51:30 2013 -0500
ARM: gic: add missing distributor defintions
Add missing register map offsets for the distributor and rename GIC_DIST_ACTIVE_BIT to GIC_DIST_ACTIVE_SET to be consistent.
(quoted diff) +0 -0
b/arch/arm/include/asm/hardware/gic.h
index dd1add1..6cad421 100644
arch/arm/include/asm/hardware/gic.h +3 -1
@@ -22,11 +22,13 @@#define GIC_DIST_CTRL 0x000#define GIC_DIST_CTR 0x004 +#define GIC_DIST_IGROUP 0x080#define GIC_DIST_ENABLE_SET 0x100#define GIC_DIST_ENABLE_CLEAR 0x180#define GIC_DIST_PENDING_SET 0x200#define GIC_DIST_PENDING_CLEAR 0x280 -#define GIC_DIST_ACTIVE_BIT 0x300 +#define GIC_DIST_ACTIVE_SET 0x300 +#define GIC_DIST_ACTIVE_CLEAR 0x380#define GIC_DIST_PRI 0x400#define GIC_DIST_TARGET 0x800#define GIC_DIST_CONFIG 0xc00
--
Thanks,
-Christoffer
PATCH v5 7/12 ARM: KVM: VGIC virtual CPU interface management
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
Add VGIC virtual CPU interface code, picking pending interrupts from the distributor and stashing them in the VGIC control interface list registers.
--- arch/arm/include/asm/kvm_vgic.h | 30 ++++ arch/arm/kvm/vgic.c | 327 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-)
arch/arm/include/asm/kvm_vgic.h +30 -0
@@ -110,8 +110,33 @@ struct vgic_dist { };struct vgic_cpu { +#ifdef CONFIG_KVM_ARM_VGIC +/* per IRQ to LR mapping */ +u8 vgic_irq_lr_map[VGIC_NR_IRQS ]; + +/* Pending interrupts on this VCPU */ + DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS); + DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS); + +/* Bitmap of used/free list registers */ + DECLARE_BITMAP( lr_used, 64); + +/* Number of list registers on this CPU */ +int nr_lr; + +/* CPU vif control registers for world switch */ +u32 vgic_hcr; +u32 vgic_vmcr; +u32 vgic_misr;/* Saved only */ +u32 vgic_eisr[2 ];/* Saved only */ +u32 vgic_elrsr[2 ];/* Saved only */ +u32 vgic_apr; +u32 vgic_lr[64 ];/* A15 has only 4... */ +#endif }; +#define LR_EMPTY 0xff +struct kvm ;struct kvm_vcpu ;struct kvm_run ;
@@ -119,9 +144,14 @@ struct kvm_exit_mmio;#ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr); +void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu); +void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu); +int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio); +#define irqchip_in_kernel (k) (!!((k)->arch.vgic.vctrl_base)) +#else static inline int kvm_vgic_hyp_init (void ) {
arch/arm/kvm/vgic.c +326 -1
345 lines not on this page · raw message
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 33 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Add VGIC virtual CPU interface code, picking pending interrupts from the distributor and stashing them in the VGIC control interface list registers.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/include/asm/kvm_vgic.h | 30 ++++ arch/arm/kvm/vgic.c | 327 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-)arch/arm/include/asm/kvm_vgic.h +12
-0@@ -110,8 +110,33 @@ struct vgic_dist { };struct vgic_cpu { +#ifdef CONFIG_KVM_ARM_VGIC +/* per IRQ to LR mapping */ +u8 vgic_irq_lr_map[VGIC_NR_IRQS ]; + +/* Pending interrupts on this VCPU */ + DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS); + DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS); + +/* Bitmap of used/free list registers */ + DECLARE_BITMAP( lr_used, 64); + +/* Number of list registers on this CPU */
arch/arm/include/asm/kvm_vgic.h struct vgic_dist { · line 134
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+int nr_lr; + +/* CPU vif control registers for world switch */ +u32 vgic_hcr; +u32 vgic_vmcr; +u32 vgic_misr;/* Saved only */ +u32 vgic_eisr[2 ];/* Saved only */ +u32 vgic_elrsr[2 ];/* Saved only */ +u32 vgic_apr; +u32 vgic_lr[64 ];/* A15 has only 4... */
Have a #define for the maximum number of list registers.
Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+#endif }; +#define LR_EMPTY 0xff +struct kvm ;struct kvm_vcpu ;struct kvm_run ;
arch/arm/include/asm/kvm_vgic.h struct kvm_exit_mmio; · line 148
Quoted 5 lines
arch/arm/include/asm/kvm_vgic.h +2
-0@@ -119,9 +144,14 @@ struct kvm_exit_mmio;#ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr); +void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu); +void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu);
Same comment as for the arch timer (flush/sync).
Quoted 90 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio); +#define irqchip_in_kernel (k) (!!((k)->arch.vgic.vctrl_base)) +#else static inline int kvm_vgic_hyp_init (void ) {arch/arm/kvm/vgic.c +58
-1@@ -152,6 +152,34 @@ static int vgic_irq_is_enabled(struct kvm_vcpu *vcpu, int irq)return vgic_bitmap_get_irq_val (&dist->irq_enabled, vcpu->vcpu_id, irq); } +static int vgic_irq_is_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_active, vcpu->vcpu_id, irq); +} + +static void vgic_irq_set_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,1 ); +} + +static void vgic_irq_clear_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,0 ); +} + +static int vgic_dist_irq_is_pending (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_state, vcpu->vcpu_id, irq); +} +static void vgic_dist_irq_set (struct kvm_vcpu *vcpu,int irq) {struct vgic_dist *dist = &vcpu->kvm->arch.vgic;@@ -711,7 +739,30 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)static int compute_pending_for_cpu (struct kvm_vcpu *vcpu) { -return 0 ; +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; +unsigned long *pending, *enabled, *pend_percpu, *pend_shared; +unsigned long pending_private, pending_shared; +int vcpu_id; + + vcpu_id = vcpu->vcpu_id; + pend_percpu = vcpu->arch.vgic_cpu.pending_percpu; + pend_shared = vcpu->arch.vgic_cpu.pending_shared; + + pending =vgic_bitmap_get_cpu_map (&dist->irq_state, vcpu_id); + enabled =vgic_bitmap_get_cpu_map (&dist->irq_enabled, vcpu_id); +bitmap_and (pend_percpu, pending, enabled,VGIC_NR_PRIVATE_IRQS ); + + pending =vgic_bitmap_get_shared_map (&dist->irq_state); + enabled =vgic_bitmap_get_shared_map (&dist->irq_enabled); +bitmap_and (pend_shared, pending, enabled,VGIC_NR_SHARED_IRQS ); +bitmap_and (pend_shared, pend_shared, +vgic_bitmap_get_shared_map (&dist->irq_spi_target[vcpu_id]), +VGIC_NR_SHARED_IRQS ); + + pending_private =find_first_bit (pend_percpu,VGIC_NR_PRIVATE_IRQS ); + pending_shared =find_first_bit (pend_shared,VGIC_NR_SHARED_IRQS ); +return (pending_private <VGIC_NR_PRIVATE_IRQS || + pending_shared <VGIC_NR_SHARED_IRQS ); }/* @@ -737,6 +788,280 @@ static void vgic_update_state(struct kvm *kvm) } } +#define LR_CPUID (lr) \ + (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) +#define MK_LR_PEND (src, irq) \ + (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) +/* +* Queue an interrupt to a CPU virtual interface. Return true on success,
arch/arm/kvm/vgic.c static void vgic_update_state(struct kvm *kvm) · line 806
Quoted 10 lines
arch/arm/kvm/vgic.c +10
-0+* or false if it wasn't possible to queue it. +*/ +static bool vgic_queue_irq (struct kvm_vcpu *vcpu,u8 sgi_source_id,int irq) +{ +struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; +int lr; + +/* Sanitize the input... */ +BUG_ON (sgi_source_id & ~7 ); +BUG_ON (sgi_source_id && irq >15 );
You can use your new NR_SGIS definition here.
Will
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 158 lines · Will Deacon
Quoted 33 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Add VGIC virtual CPU interface code, picking pending interrupts from the distributor and stashing them in the VGIC control interface list registers.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/include/asm/kvm_vgic.h | 30 ++++ arch/arm/kvm/vgic.c | 327 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-)arch/arm/include/asm/kvm_vgic.h +12
-0@@ -110,8 +110,33 @@ struct vgic_dist { };struct vgic_cpu { +#ifdef CONFIG_KVM_ARM_VGIC +/* per IRQ to LR mapping */ +u8 vgic_irq_lr_map[VGIC_NR_IRQS ]; + +/* Pending interrupts on this VCPU */ + DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS); + DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS); + +/* Bitmap of used/free list registers */ + DECLARE_BITMAP( lr_used, 64); + +/* Number of list registers on this CPU */ arch/arm/include/asm/kvm_vgic.h struct vgic_dist { · line 134
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+int nr_lr; + +/* CPU vif control registers for world switch */ +u32 vgic_hcr; +u32 vgic_vmcr; +u32 vgic_misr;/* Saved only */ +u32 vgic_eisr[2 ];/* Saved only */ +u32 vgic_elrsr[2 ];/* Saved only */ +u32 vgic_apr; +u32 vgic_lr[64 ];/* A15 has only 4... */ Have a #define for the maximum number of list registers.
Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+#endif }; +#define LR_EMPTY 0xff +struct kvm ;struct kvm_vcpu ;struct kvm_run ;arch/arm/include/asm/kvm_vgic.h struct kvm_exit_mmio; · line 148
Quoted 5 lines
arch/arm/include/asm/kvm_vgic.h +2
-0@@ -119,9 +144,14 @@ struct kvm_exit_mmio;#ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr); +void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu); +void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu);Same comment as for the arch timer (flush/sync).
Quoted 94 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio); +#define irqchip_in_kernel (k) (!!((k)->arch.vgic.vctrl_base)) +#else static inline int kvm_vgic_hyp_init (void ) {arch/arm/kvm/vgic.c +62
-1@@ -152,6 +152,34 @@ static int vgic_irq_is_enabled(struct kvm_vcpu *vcpu, int irq)return vgic_bitmap_get_irq_val (&dist->irq_enabled, vcpu->vcpu_id, irq); } +static int vgic_irq_is_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_active, vcpu->vcpu_id, irq); +} + +static void vgic_irq_set_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,1 ); +} + +static void vgic_irq_clear_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,0 ); +} + +static int vgic_dist_irq_is_pending (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_state, vcpu->vcpu_id, irq); +} +static void vgic_dist_irq_set (struct kvm_vcpu *vcpu,int irq) {struct vgic_dist *dist = &vcpu->kvm->arch.vgic;@@ -711,7 +739,30 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)static int compute_pending_for_cpu (struct kvm_vcpu *vcpu) { -return 0 ; +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; +unsigned long *pending, *enabled, *pend_percpu, *pend_shared; +unsigned long pending_private, pending_shared; +int vcpu_id; + + vcpu_id = vcpu->vcpu_id; + pend_percpu = vcpu->arch.vgic_cpu.pending_percpu; + pend_shared = vcpu->arch.vgic_cpu.pending_shared; + + pending =vgic_bitmap_get_cpu_map (&dist->irq_state, vcpu_id); + enabled =vgic_bitmap_get_cpu_map (&dist->irq_enabled, vcpu_id); +bitmap_and (pend_percpu, pending, enabled,VGIC_NR_PRIVATE_IRQS ); + + pending =vgic_bitmap_get_shared_map (&dist->irq_state); + enabled =vgic_bitmap_get_shared_map (&dist->irq_enabled); +bitmap_and (pend_shared, pending, enabled,VGIC_NR_SHARED_IRQS ); +bitmap_and (pend_shared, pend_shared, +vgic_bitmap_get_shared_map (&dist->irq_spi_target[vcpu_id]), +VGIC_NR_SHARED_IRQS ); + + pending_private =find_first_bit (pend_percpu,VGIC_NR_PRIVATE_IRQS ); + pending_shared =find_first_bit (pend_shared,VGIC_NR_SHARED_IRQS ); +return (pending_private <VGIC_NR_PRIVATE_IRQS || + pending_shared <VGIC_NR_SHARED_IRQS ); }/* @@ -737,6 +788,280 @@ static void vgic_update_state(struct kvm *kvm) } } +#define LR_CPUID (lr) \ + (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) +#define MK_LR_PEND (src, irq) \ + (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) +/* +* Queue an interrupt to a CPU virtual interface. Return true on success, +* or false if it wasn't possible to queue it. +*/ +static bool vgic_queue_irq (struct kvm_vcpu *vcpu,u8 sgi_source_id,int irq) +{
Quoted 9 lines
arch/arm/kvm/vgic.c static void vgic_update_state(struct kvm *kvm) · line 806
Quoted 6 lines
arch/arm/kvm/vgic.c +6
-0+struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; +int lr; + +/* Sanitize the input... */ +BUG_ON (sgi_source_id & ~7 ); +BUG_ON (sgi_source_id && irq >15 );You can use your new
NR_SGISdefinition here.
This should address the remaining comments:
commit 43957095ec5476beb198f4c4630dfc3e2f3951db
Author: Christoffer Dall <[email protected]> Date: Mon Jan 14 16:59:38 2013 -0500
KVM: ARM: vgic: Define VGIC_MAX_LRS
Define maximum number of link registers we can handle instead of using literals in the code. If an architecture reports more link registers than we support, only use the number we can support.
arch/arm/include/asm/kvm_vgic.h +3 -2
@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )
@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;
@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };
arch/arm/kvm/vgic.c +2 -0
@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void) vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ; +if (vgic_nr_lr >VGIC_MAX_LRS ) + vgic_nr_lr =VGIC_MAX_LRS ;/* TODO: Clear remaining LRs */ ret = create_hyp_io_mappings(vgic_vctrl_base, vgic_vctrl_base + resource_size(&vctrl_res),
--
Thanks,
-Christoffer
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 188 lines · Christoffer Dall
Quoted 158 lines · Will Deacon
Quoted 33 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Add VGIC virtual CPU interface code, picking pending interrupts from the distributor and stashing them in the VGIC control interface list registers.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/include/asm/kvm_vgic.h | 30 ++++ arch/arm/kvm/vgic.c | 327 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-)arch/arm/include/asm/kvm_vgic.h +12
-0@@ -110,8 +110,33 @@ struct vgic_dist { };struct vgic_cpu { +#ifdef CONFIG_KVM_ARM_VGIC +/* per IRQ to LR mapping */ +u8 vgic_irq_lr_map[VGIC_NR_IRQS ]; + +/* Pending interrupts on this VCPU */ + DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS); + DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS); + +/* Bitmap of used/free list registers */ + DECLARE_BITMAP( lr_used, 64); + +/* Number of list registers on this CPU */ arch/arm/include/asm/kvm_vgic.h struct vgic_dist { · line 134
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+int nr_lr; + +/* CPU vif control registers for world switch */ +u32 vgic_hcr; +u32 vgic_vmcr; +u32 vgic_misr;/* Saved only */ +u32 vgic_eisr[2 ];/* Saved only */ +u32 vgic_elrsr[2 ];/* Saved only */ +u32 vgic_apr; +u32 vgic_lr[64 ];/* A15 has only 4... */ Have a #define for the maximum number of list registers.
Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+#endif }; +#define LR_EMPTY 0xff +struct kvm ;struct kvm_vcpu ;struct kvm_run ;arch/arm/include/asm/kvm_vgic.h struct kvm_exit_mmio; · line 148
Quoted 5 lines
arch/arm/include/asm/kvm_vgic.h +2
-0@@ -119,9 +144,14 @@ struct kvm_exit_mmio;#ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr); +void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu); +void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu);Same comment as for the arch timer (flush/sync).
Quoted 94 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio); +#define irqchip_in_kernel (k) (!!((k)->arch.vgic.vctrl_base)) +#else static inline int kvm_vgic_hyp_init (void ) {arch/arm/kvm/vgic.c +62
-1@@ -152,6 +152,34 @@ static int vgic_irq_is_enabled(struct kvm_vcpu *vcpu, int irq)return vgic_bitmap_get_irq_val (&dist->irq_enabled, vcpu->vcpu_id, irq); } +static int vgic_irq_is_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_active, vcpu->vcpu_id, irq); +} + +static void vgic_irq_set_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,1 ); +} + +static void vgic_irq_clear_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,0 ); +} + +static int vgic_dist_irq_is_pending (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_state, vcpu->vcpu_id, irq); +} +static void vgic_dist_irq_set (struct kvm_vcpu *vcpu,int irq) {struct vgic_dist *dist = &vcpu->kvm->arch.vgic;@@ -711,7 +739,30 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)static int compute_pending_for_cpu (struct kvm_vcpu *vcpu) { -return 0 ; +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; +unsigned long *pending, *enabled, *pend_percpu, *pend_shared; +unsigned long pending_private, pending_shared; +int vcpu_id; + + vcpu_id = vcpu->vcpu_id; + pend_percpu = vcpu->arch.vgic_cpu.pending_percpu; + pend_shared = vcpu->arch.vgic_cpu.pending_shared; + + pending =vgic_bitmap_get_cpu_map (&dist->irq_state, vcpu_id); + enabled =vgic_bitmap_get_cpu_map (&dist->irq_enabled, vcpu_id); +bitmap_and (pend_percpu, pending, enabled,VGIC_NR_PRIVATE_IRQS ); + + pending =vgic_bitmap_get_shared_map (&dist->irq_state); + enabled =vgic_bitmap_get_shared_map (&dist->irq_enabled); +bitmap_and (pend_shared, pending, enabled,VGIC_NR_SHARED_IRQS ); +bitmap_and (pend_shared, pend_shared, +vgic_bitmap_get_shared_map (&dist->irq_spi_target[vcpu_id]), +VGIC_NR_SHARED_IRQS ); + + pending_private =find_first_bit (pend_percpu,VGIC_NR_PRIVATE_IRQS ); + pending_shared =find_first_bit (pend_shared,VGIC_NR_SHARED_IRQS ); +return (pending_private <VGIC_NR_PRIVATE_IRQS || + pending_shared <VGIC_NR_SHARED_IRQS ); }/* @@ -737,6 +788,280 @@ static void vgic_update_state(struct kvm *kvm) } } +#define LR_CPUID (lr) \ + (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) +#define MK_LR_PEND (src, irq) \ + (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) +/* +* Queue an interrupt to a CPU virtual interface. Return true on success, +* or false if it wasn't possible to queue it. +*/ +static bool vgic_queue_irq (struct kvm_vcpu *vcpu,u8 sgi_source_id,int irq) +{Quoted 9 lines
arch/arm/kvm/vgic.c static void vgic_update_state(struct kvm *kvm) · line 806
Quoted 6 lines
arch/arm/kvm/vgic.c +6
-0+struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; +int lr; + +/* Sanitize the input... */ +BUG_ON (sgi_source_id & ~7 ); +BUG_ON (sgi_source_id && irq >15 );You can use your new
NR_SGISdefinition here.This should address the remaining comments:
commit
43957095ec5476beb198f4c4630dfc3e2f3951dbAuthor: Christoffer Dall <[email protected]> Date: Mon Jan 14 16:59:38 2013 -0500KVM: ARM: vgic: Define
VGIC_MAX_LRSDefine maximum number of link registers we can handle instead of using literals in the code. If an architecture reports more link registers than we support, only use the number we can support.
Signed-off-by Christoffer Dall <[email protected]>arch/arm/include/asm/kvm_vgic.h +0
-0
arch/arm/include/asm/kvm_vgic.h line 36
Quoted 4 lines
arch/arm/include/asm/kvm_vgic.h +1
-0@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64
Consider this instead (for the reason below)
#define VGIC_MAX_LRS (1 << 7)
Quoted 25 lines
arch/arm/include/asm/kvm_vgic.h +2
-2/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };arch/arm/kvm/vgic.c +0
-0
arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1347
Quoted 3 lines
arch/arm/kvm/vgic.c +0
-0@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void) vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ;
There is a bug here. It should be:
vgic_nr_lr = (vgic_nr_lr & 0x2f) + 1;
arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1349
Quoted 2 lines
arch/arm/kvm/vgic.c +2
-0+if (vgic_nr_lr >VGIC_MAX_LRS ) + vgic_nr_lr =VGIC_MAX_LRS ;/* TODO: Clear remaining LRs */
Why? VGIC_MAX_LRS isn't a configurable value, but a maximum value defined by the specification. This is the maximum you can fit in a 6 bit field, plus one (1 << 7, exactly).
Quoted 7 lines
arch/arm/kvm/vgic.c +0
-1ret = create_hyp_io_mappings(vgic_vctrl_base, vgic_vctrl_base + resource_size(&vctrl_res), --Thanks,
-Christoffer
Signature · 1 line
Jazz is not dead. It just smells funny...
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 227 lines · Marc Zyngier
Quoted 188 lines · Christoffer Dall
Quoted 158 lines · Will Deacon
Quoted 33 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
Add VGIC virtual CPU interface code, picking pending interrupts from the distributor and stashing them in the VGIC control interface list registers.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/include/asm/kvm_vgic.h | 30 ++++ arch/arm/kvm/vgic.c | 327 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-)arch/arm/include/asm/kvm_vgic.h +12
-0@@ -110,8 +110,33 @@ struct vgic_dist { };struct vgic_cpu { +#ifdef CONFIG_KVM_ARM_VGIC +/* per IRQ to LR mapping */ +u8 vgic_irq_lr_map[VGIC_NR_IRQS ]; + +/* Pending interrupts on this VCPU */ + DECLARE_BITMAP( pending_percpu, VGIC_NR_PRIVATE_IRQS); + DECLARE_BITMAP( pending_shared, VGIC_NR_SHARED_IRQS); + +/* Bitmap of used/free list registers */ + DECLARE_BITMAP( lr_used, 64); + +/* Number of list registers on this CPU */ arch/arm/include/asm/kvm_vgic.h struct vgic_dist { · line 134
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +10
-0+int nr_lr; + +/* CPU vif control registers for world switch */ +u32 vgic_hcr; +u32 vgic_vmcr; +u32 vgic_misr;/* Saved only */ +u32 vgic_eisr[2 ];/* Saved only */ +u32 vgic_elrsr[2 ];/* Saved only */ +u32 vgic_apr; +u32 vgic_lr[64 ];/* A15 has only 4... */ Have a #define for the maximum number of list registers.
Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+#endif }; +#define LR_EMPTY 0xff +struct kvm ;struct kvm_vcpu ;struct kvm_run ;arch/arm/include/asm/kvm_vgic.h struct kvm_exit_mmio; · line 148
Quoted 5 lines
arch/arm/include/asm/kvm_vgic.h +2
-0@@ -119,9 +144,14 @@ struct kvm_exit_mmio;#ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr); +void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu); +void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu);Same comment as for the arch timer (flush/sync).
Quoted 94 lines
arch/arm/include/asm/kvm_vgic.h +3
-0+int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio); +#define irqchip_in_kernel (k) (!!((k)->arch.vgic.vctrl_base)) +#else static inline int kvm_vgic_hyp_init (void ) {arch/arm/kvm/vgic.c +62
-1@@ -152,6 +152,34 @@ static int vgic_irq_is_enabled(struct kvm_vcpu *vcpu, int irq)return vgic_bitmap_get_irq_val (&dist->irq_enabled, vcpu->vcpu_id, irq); } +static int vgic_irq_is_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_active, vcpu->vcpu_id, irq); +} + +static void vgic_irq_set_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,1 ); +} + +static void vgic_irq_clear_active (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +vgic_bitmap_set_irq_val (&dist->irq_active, vcpu->vcpu_id, irq,0 ); +} + +static int vgic_dist_irq_is_pending (struct kvm_vcpu *vcpu,int irq) +{ +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; + +return vgic_bitmap_get_irq_val (&dist->irq_state, vcpu->vcpu_id, irq); +} +static void vgic_dist_irq_set (struct kvm_vcpu *vcpu,int irq) {struct vgic_dist *dist = &vcpu->kvm->arch.vgic;@@ -711,7 +739,30 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)static int compute_pending_for_cpu (struct kvm_vcpu *vcpu) { -return 0 ; +struct vgic_dist *dist = &vcpu->kvm->arch.vgic; +unsigned long *pending, *enabled, *pend_percpu, *pend_shared; +unsigned long pending_private, pending_shared; +int vcpu_id; + + vcpu_id = vcpu->vcpu_id; + pend_percpu = vcpu->arch.vgic_cpu.pending_percpu; + pend_shared = vcpu->arch.vgic_cpu.pending_shared; + + pending =vgic_bitmap_get_cpu_map (&dist->irq_state, vcpu_id); + enabled =vgic_bitmap_get_cpu_map (&dist->irq_enabled, vcpu_id); +bitmap_and (pend_percpu, pending, enabled,VGIC_NR_PRIVATE_IRQS ); + + pending =vgic_bitmap_get_shared_map (&dist->irq_state); + enabled =vgic_bitmap_get_shared_map (&dist->irq_enabled); +bitmap_and (pend_shared, pending, enabled,VGIC_NR_SHARED_IRQS ); +bitmap_and (pend_shared, pend_shared, +vgic_bitmap_get_shared_map (&dist->irq_spi_target[vcpu_id]), +VGIC_NR_SHARED_IRQS ); + + pending_private =find_first_bit (pend_percpu,VGIC_NR_PRIVATE_IRQS ); + pending_shared =find_first_bit (pend_shared,VGIC_NR_SHARED_IRQS ); +return (pending_private <VGIC_NR_PRIVATE_IRQS || + pending_shared <VGIC_NR_SHARED_IRQS ); }/* @@ -737,6 +788,280 @@ static void vgic_update_state(struct kvm *kvm) } } +#define LR_CPUID (lr) \ + (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT) +#define MK_LR_PEND (src, irq) \ + (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) +/* +* Queue an interrupt to a CPU virtual interface. Return true on success, +* or false if it wasn't possible to queue it. +*/ +static bool vgic_queue_irq (struct kvm_vcpu *vcpu,u8 sgi_source_id,int irq) +{Quoted 9 lines
arch/arm/kvm/vgic.c static void vgic_update_state(struct kvm *kvm) · line 806
Quoted 6 lines
arch/arm/kvm/vgic.c +6
-0+struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; +int lr; + +/* Sanitize the input... */ +BUG_ON (sgi_source_id & ~7 ); +BUG_ON (sgi_source_id && irq >15 );You can use your new
NR_SGISdefinition here.This should address the remaining comments:
commit
43957095ec5476beb198f4c4630dfc3e2f3951dbAuthor: Christoffer Dall <[email protected]> Date: Mon Jan 14 16:59:38 2013 -0500KVM: ARM: vgic: Define
VGIC_MAX_LRSDefine maximum number of link registers we can handle instead of using literals in the code. If an architecture reports more link registers than we support, only use the number we can support.
Signed-off-by Christoffer Dall <[email protected]>arch/arm/include/asm/kvm_vgic.h +0
-0arch/arm/include/asm/kvm_vgic.h line 36
Quoted 4 lines
arch/arm/include/asm/kvm_vgic.h +1
-0@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64Consider this instead (for the reason below)
#defineVGIC_MAX_LRS(1 << 7)Quoted 25 lines
arch/arm/include/asm/kvm_vgic.h +2
-2/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };arch/arm/kvm/vgic.c +0
-0arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1347
Quoted 3 lines
arch/arm/kvm/vgic.c +0
-0@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void) vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ;There is a bug here. It should be:
Quoted 9 lines
vgic_nr_lr = (vgic_nr_lr & 0x2f) + 1;arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1349
Quoted 2 lines
arch/arm/kvm/vgic.c +2
-0+if (vgic_nr_lr >VGIC_MAX_LRS ) + vgic_nr_lr =VGIC_MAX_LRS ;/* TODO: Clear remaining LRs */ Why?
VGIC_MAX_LRSisn't a configurable value, but a maximum value defined by the specification. This is the maximum you can fit in a 6 bit field, plus one (1 << 7, exactly).
I figures this was something that could potentially change with a newer gic architecture etc., and then it was good to have the check, but you're right, then everything would break.
-Christoffer
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
In reply to Marc Zyngier[...]
Quoted 4 lines
Quoted 4 lines
arch/arm/include/asm/kvm_vgic.h +0
-0
Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h line 36
Quoted 5 lines
arch/arm/include/asm/kvm_vgic.h +1
-0@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64Consider this instead (for the reason below)
#defineVGIC_MAX_LRS(1 << 7)
so here you mean (1 << 6), right?
Quoted 26 lines
Quoted 26 lines
arch/arm/include/asm/kvm_vgic.h +2
-2/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };arch/arm/kvm/vgic.c +0
-0@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void)
Quoted 6 lines
arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1347
Quoted 2 lines
arch/arm/kvm/vgic.c +0
-0vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ;There is a bug here. It should be:
vgic_nr_lr = (vgic_nr_lr & 0x2f) + 1;
and here you mean (vgic_nr_lr & 0x3f) + 1
right?
Quoted 19 lines
arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1349
Quoted 2 lines
arch/arm/kvm/vgic.c +2
-0+if (vgic_nr_lr >VGIC_MAX_LRS ) + vgic_nr_lr =VGIC_MAX_LRS ;/* TODO: Clear remaining LRs */ Why?
VGIC_MAX_LRSisn't a configurable value, but a maximum value defined by the specification. This is the maximum you can fit in a 6 bit field, plus one (1 << 7, exactly).Quoted 7 lines
arch/arm/kvm/vgic.c +0
-1ret = create_hyp_io_mappings(vgic_vctrl_base, vgic_vctrl_base + resource_size(&vctrl_res), --Thanks,
-Christoffer--
Jazz is not dead. It just smells funny...
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 16 lines · Christoffer Dall
[...]
Quoted 4 lines
Quoted 4 lines
arch/arm/include/asm/kvm_vgic.h +0
-0Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h line 36
Quoted 5 lines
arch/arm/include/asm/kvm_vgic.h +1
-0@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64Consider this instead (for the reason below)
#defineVGIC_MAX_LRS(1 << 7)
Quoted 1 line
so here you mean (1 << 6), right?
No. We have a 6 bit field that contains (NR_LRS - 1). So the maximum value is (0b111111 + 1), which is (1 << 7).
Quoted 34 lines
Quoted 27 lines
Quoted 27 lines
arch/arm/include/asm/kvm_vgic.h +2
-2/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };arch/arm/kvm/vgic.c +0
-0@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void)Quoted 6 lines
arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1347
Quoted 2 lines
arch/arm/kvm/vgic.c +0
-0vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ;There is a bug here. It should be:
vgic_nr_lr = (vgic_nr_lr & 0x2f) + 1;
Quoted 2 lines
and here you mean (
vgic_nr_lr&0x3f) + 1
right?
Neither. 0x2f is the right value. See the GIC spec, 5.3.2, GICH_VTR register.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Re: [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 17 lines · Marc Zyngier
Quoted 16 lines · Christoffer Dall
[...]
Quoted 13 lines
arch/arm/include/asm/kvm_vgic.h line 36
Quoted 9 lines
arch/arm/include/asm/kvm_vgic.h +1
-0@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64Consider this instead (for the reason below)
#defineVGIC_MAX_LRS(1 << 7)
Quoted 5 lines
Quoted 1 line
so here you mean (1 << 6), right?
No. We have a 6 bit field that contains (
NR_LRS- 1). So the maximum value is (0b111111+ 1), which is (1 << 7).
eh, (1 << 7) is 128, and we have a maximum value of 63 (which plus the one is 64). You can verify this by thinking about having four bits, is a halfword, which we use hex numbers to deal with, so the number of values you can decode there is 16, then you have two more bits, which each doubles the number of values, so this becomes 64 values total, ie. from 0 through 63. :)
Quoted 34 lines
Quoted 34 lines
Quoted 33 lines
Quoted 26 lines
arch/arm/include/asm/kvm_vgic.h +2
-2/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };arch/arm/kvm/vgic.c +0
-0arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1347
Quoted 3 lines
arch/arm/kvm/vgic.c +0
-0@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void) vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ;There is a bug here. It should be:
vgic_nr_lr = (vgic_nr_lr & 0x2f) + 1;
Quoted 6 lines
Quoted 2 lines
and here you mean (
vgic_nr_lr&0x3f) + 1
right?Neither.
0x2fis the right value. See the GIC spec, 5.3.2,GICH_VTRregister.
I'm looking at it, and I don't understand why you don't want to consider bit[4] ?
-Christoffer
Re: [kvmarm] [PATCH v5 07/12] ARM: KVM: VGIC virtual CPU interface management
Quoted 26 lines · Christoffer Dall
Quoted 18 lines · Marc Zyngier
Quoted 17 lines · Christoffer Dall
[...]
Quoted 14 lines
arch/arm/include/asm/kvm_vgic.h line 36
Quoted 10 lines
arch/arm/include/asm/kvm_vgic.h +1
-0@@ -33,6 +33,7 @@#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)#define VGIC_NR_SHARED_IRQS (VGIC_NR_IRQS - VGIC_NR_PRIVATE_IRQS)#define VGIC_MAX_CPUS KVM_MAX_VCPUS +#define VGIC_MAX_LRS 64Consider this instead (for the reason below)
#defineVGIC_MAX_LRS(1 << 7)Quoted 5 lines
Quoted 1 line
so here you mean (1 << 6), right?
No. We have a 6 bit field that contains (
NR_LRS- 1). So the maximum value is (0b111111+ 1), which is (1 << 7).
Quoted 7 lines
eh, (1 << 7) is 128, and we have a maximum value of 63 (which plus the one is 64). You can verify this by thinking about having four bits, is a halfword, which we use hex numbers to deal with, so the number of values you can decode there is 16, then you have two more bits, which each doubles the number of values, so this becomes 64 values total, ie. from 0 through 63. :)
Blah. Ignore me, I'm being stupid.
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
Quoted 35 lines
Quoted 28 lines
arch/arm/include/asm/kvm_vgic.h +2
-2/* Sanity checks... */ #if (VGIC_MAX_CPUS >8 )@@ -120,7 +121,7 @@ struct vgic_cpu {DECLARE_BITMAP ( pending_shared,VGIC_NR_SHARED_IRQS );/* Bitmap of used/free list registers */ -DECLARE_BITMAP ( lr_used,64 ); +DECLARE_BITMAP ( lr_used,VGIC_MAX_LRS );/* Number of list registers on this CPU */ int nr_lr;@@ -132,7 +133,7 @@ struct vgic_cpu {u32 vgic_eisr[2 ];/* Saved only */ u32 vgic_elrsr[2 ];/* Saved only */ u32 vgic_apr; -u32 vgic_lr[64 ];/* A15 has only 4... */ +u32 vgic_lr[VGIC_MAX_LRS ];#endif };arch/arm/kvm/vgic.c +0
-0arch/arm/kvm/vgic.c int kvm_vgic_hyp_init(void) · line 1347
Quoted 3 lines
arch/arm/kvm/vgic.c +0
-0@@ -1345,6 +1345,8 @@ int kvm_vgic_hyp_init(void) vgic_nr_lr =readl_relaxed (vgic_vctrl_base +GICH_VTR ); vgic_nr_lr = (vgic_nr_lr &0x1f ) +1 ;There is a bug here. It should be:
vgic_nr_lr = (vgic_nr_lr & 0x2f) + 1;
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
and here you mean (
vgic_nr_lr&0x3f) + 1
right?Neither.
0x2fis the right value. See the GIC spec, 5.3.2,GICH_VTRregister.I'm looking at it, and I don't understand why you don't want to consider bit[4] ?
Because it's not a prime number? ;-)
I think I should stay away from patches these days, I'm clearly not thinking straight. Thanks for coping with my lack of brain.
M.
Signature · 1 line
Fast, cheap, reliable. Pick two.
PATCH v5 8/12 ARM: KVM: vgic: retire queued, disabled interrupts
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
An interrupt may have been disabled after being made pending on the CPU interface (the classic case is a timer running while we're rebooting the guest - the interrupt would kick as soon as the CPU interface gets enabled, with deadly consequences).
The solution is to examine already active LRs, and check the interrupt is still enabled. If not, just retire it.
--- arch/arm/kvm/vgic.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
arch/arm/kvm/vgic.c +30 -0
@@ -71,6 +71,7 @@#define ACCESS_WRITE_VALUE (3 << 1)#define ACCESS_WRITE_MASK (x) ((x) & (3 << 1)) +static void vgic_retire_disabled_irqs (struct kvm_vcpu *vcpu);static void vgic_update_state (struct kvm *kvm);static void vgic_dispatch_sgi (struct kvm_vcpu *vcpu,u32 reg);
@@ -344,6 +345,7 @@ static bool handle_mmio_clear_enable_reg(struct kvm_vcpu *vcpu,if (mmio->is_write) {if (offset <4 )/* Force SGI enabled */ *reg |=0xffff ; +vgic_retire_disabled_irqs (vcpu);vgic_update_state (vcpu->kvm);return true; }
@@ -792,6 +794,34 @@ static void vgic_update_state(struct kvm *kvm) (((lr) & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT)#define MK_LR_PEND (src, irq) \ (GICH_LR_PENDING_BIT | ((src) << GICH_LR_PHYSID_CPUID_SHIFT) | (irq)) + +/* +* An interrupt may have been disabled after being made pending on the +* CPU interface (the classic case is a timer running while we're +* rebooting the guest - the interrupt would kick as soon as the CPU +* interface gets enabled, with deadly consequences). +* +* The solution is to examine already active LRs, and check the +* interrupt is still enabled. If not, just retire it. +*/ +static void vgic_retire_disabled_irqs (struct kvm_vcpu *vcpu) +{ +struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; +int lr; + +for_each_set_bit (lr, vgic_cpu->lr_used, vgic_cpu->nr_lr) { +int irq = vgic_cpu->vgic_lr[lr] &GICH_LR_VIRTUALID ; + +if (!vgic_irq_is_enabled (vcpu, irq)) { + vgic_cpu->vgic_irq_lr_map[irq] =LR_EMPTY ; +clear_bit (lr, vgic_cpu->lr_used); + vgic_cpu->vgic_lr[lr] &= ~GICH_LR_STATE ; +if (vgic_irq_is_active (vcpu, irq)) +vgic_irq_clear_active (vcpu, irq); + } + } +} +/* * Queue an interrupt to a CPU virtual interface. Return true on success, * or false if it wasn't possible to queue it.
PATCH v5 9/12 ARM: KVM: VGIC interrupt injection
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
Plug the interrupt injection code. Interrupts can now be generated from user space.
--- arch/arm/include/asm/kvm_vgic.h | 8 +++ arch/arm/kvm/arm.c | 55 +++++++++++++++--- arch/arm/kvm/vgic.c | 117 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 10 deletions(-)
arch/arm/include/asm/kvm_vgic.h +8 -0
@@ -146,6 +146,8 @@ struct kvm_exit_mmio;int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr);void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu);void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu); +int kvm_vgic_inject_irq (struct kvm *kvm,int cpuid,unsigned int irq_num, +bool level);int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio);
@@ -181,6 +183,12 @@ static inline int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)static inline void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu) {}static inline void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu) {} +static inline int kvm_vgic_inject_irq (struct kvm *kvm,int cpuid, +unsigned int irq_num,bool level) +{ +return 0 ; +} +static inline int kvm_vgic_vcpu_pending_irq (struct kvm_vcpu *vcpu) {return 0 ;
arch/arm/kvm/arm.c +45 -10
71 lines not on this page · raw message
arch/arm/kvm/vgic.c +117 -0
135 lines not on this page · raw message
PATCH v5 10/12 ARM: KVM: VGIC control interface world switch
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
Enable the VGIC control interface to be save-restored on world switch.
--- arch/arm/kernel/asm-offsets.c | 12 ++++++ arch/arm/kvm/interrupts_head.S | 74 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+)
arch/arm/kernel/asm-offsets.c +12 -0
@@ -169,6 +169,18 @@ int main(void) DEFINE(VCPU_HxFAR, offsetof(struct kvm_vcpu, arch.hxfar)); DEFINE(VCPU_HPFAR, offsetof(struct kvm_vcpu, arch.hpfar)); DEFINE(VCPU_HYP_PC, offsetof(struct kvm_vcpu, arch.hyp_pc)); +#ifdef CONFIG_KVM_ARM_VGIC + DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu)); +DEFINE (VGIC_CPU_HCR , offsetof(struct vgic_cpu , vgic_hcr)); +DEFINE (VGIC_CPU_VMCR , offsetof(struct vgic_cpu , vgic_vmcr)); +DEFINE (VGIC_CPU_MISR , offsetof(struct vgic_cpu , vgic_misr)); +DEFINE (VGIC_CPU_EISR , offsetof(struct vgic_cpu , vgic_eisr)); +DEFINE (VGIC_CPU_ELRSR , offsetof(struct vgic_cpu , vgic_elrsr)); +DEFINE (VGIC_CPU_APR , offsetof(struct vgic_cpu , vgic_apr)); +DEFINE (VGIC_CPU_LR , offsetof(struct vgic_cpu , vgic_lr)); +DEFINE (VGIC_CPU_NR_LR , offsetof(struct vgic_cpu , nr_lr)); + DEFINE(KVM_VGIC_VCTRL, offsetof(struct kvm, arch.vgic.vctrl_base)); +#endif DEFINE(KVM_VTTBR, offsetof(struct kvm, arch.vttbr));#endif return 0 ;
arch/arm/kvm/interrupts_head.S +74 -0
89 lines not on this page · raw message
PATCH v5 11/12 ARM: KVM: VGIC initialisation code
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
Add the init code for the hypervisor, the virtual machine, and the virtual CPUs.
An interrupt handler is also wired to allow the VGIC maintenance interrupts, used to deal with level triggered interrupts and LR underflows.
A CPU hotplug notifier is registered to disable/enable the interrupt as requested.
--- arch/arm/include/asm/kvm_vgic.h | 11 ++ arch/arm/kvm/arm.c | 15 +++ arch/arm/kvm/vgic.c | 223 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 249 insertions(+)
arch/arm/include/asm/kvm_vgic.h +11 -0
@@ -71,6 +71,7 @@ struct vgic_bytemap {struct vgic_dist {#ifdef CONFIG_KVM_ARM_VGIC spinlock_t lock; +bool ready;/* Virtual control interface mapping */ void __iomem *vctrl_base;
@@ -144,6 +145,10 @@ struct kvm_exit_mmio;#ifdef CONFIG_KVM_ARM_VGIC int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr); +int kvm_vgic_hyp_init (void ); +int kvm_vgic_init (struct kvm *kvm); +int kvm_vgic_create (struct kvm *kvm); +int kvm_vgic_vcpu_init (struct kvm_vcpu *vcpu);void kvm_vgic_sync_to_cpu (struct kvm_vcpu *vcpu);void kvm_vgic_sync_from_cpu (struct kvm_vcpu *vcpu); int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
@@ -153,6 +158,7 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, struct kvm_exit_mmio *mmio);#define irqchip_in_kernel (k) (!!((k)->arch.vgic.vctrl_base)) +#define vgic_initialized (k) ((k)->arch.vgic.ready)#else static inline int kvm_vgic_hyp_init (void )
@@ -204,6 +210,11 @@ static inline int irqchip_in_kernel(struct kvm *kvm) {return 0 ; } + +static inline bool vgic_initialized (struct kvm *kvm) +{ +return true; +}#endif #endif
arch/arm/kvm/arm.c +15 -0
@@ -659,6 +659,17 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)if (unlikely (vcpu->arch.target <0 ))return -ENOEXEC ; +/* +* Initialize the VGIC before running a vcpu the first time on +* this VM. +*/ +if (irqchip_in_kernel (vcpu->kvm) && +unlikely (!vgic_initialized (vcpu->kvm))) { + ret =kvm_vgic_init (vcpu->kvm); +if (ret) +return ret; + } +if (run->exit_reason ==KVM_EXIT_MMIO ) { ret =kvm_handle_mmio_return (vcpu, vcpu->run);if (ret)
@@ -1066,6 +1077,10 @@ static int init_hyp_mode(void)if (err) goto out_free_vfp; +#ifdef CONFIG_KVM_ARM_VGIC + vgic_present = true; +#endif +kvm_info ("Hyp mode initialized successfully\n" );return 0 ; out_free_vfp:
arch/arm/kvm/vgic.c +223 -0
252 lines not on this page · raw message
PATCH v5 12/12 ARM: KVM: Add VGIC configuration option
In reply to Christoffer DallFrom: Marc Zyngier <[email protected]>
It is now possible to select the VGIC configuration option.
--- arch/arm/kvm/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/arm/kvm/Kconfig +8 -0
@@ -51,6 +51,14 @@ config KVM_ARM_MAX_VCPUS large, so only choose a reasonable number that you expect to actually use. +config KVM_ARM_VGIC + bool "KVM support for Virtual GIC" + depends on KVM_ARM_HOST && OF + select HAVE_KVM_IRQCHIP + default y + ---help--- + Adds support for a hardware assisted, in-kernel GIC emulation. + source drivers/virtio/Kconfig endif # VIRTUALIZATION
Re: [PATCH v5 12/12] ARM: KVM: Add VGIC configuration option
Hello.
Quoted 15 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
It is now possible to select the VGIC configuration option.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/kvm/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+)arch/arm/kvm/Kconfig +0
-0
arch/arm/kvm/Kconfig config KVM_ARM_MAX_VCPUS · line 55
Quoted 5 lines
arch/arm/kvm/Kconfig +2
-0@@ -51,6 +51,14 @@ config KVM_ARM_MAX_VCPUS large, so only choose a reasonable number that you expect to actually use. +config KVM_ARM_VGIC + bool "KVM support for Virtual GIC"
Please indent with tab, as below.
arch/arm/kvm/Kconfig config KVM_ARM_MAX_VCPUS · line 61
Quoted 6 lines
arch/arm/kvm/Kconfig +6
-0+ depends on KVM_ARM_HOST && OF + select HAVE_KVM_IRQCHIP + default y + ---help--- + Adds support for a hardware assisted, in-kernel GIC emulation. +
WBR, Sergei
Re: [PATCH v5 12/12] ARM: KVM: Add VGIC configuration option
Quoted 26 lines · Sergei Shtylyov
Hello.
Quoted 21 lines · Christoffer Dall
From: Marc Zyngier <[email protected]>
It is now possible to select the VGIC configuration option.
Signed-off-by Marc Zyngier <[email protected]>Signed-off-by Christoffer Dall <[email protected]>--- arch/arm/kvm/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+)arch/arm/kvm/Kconfig +0
-0@@ -51,6 +51,14 @@ config KVM_ARM_MAX_VCPUS large, so only choose a reasonable number that you expect to actually use.
Quoted 7 lines
arch/arm/kvm/Kconfig config KVM_ARM_MAX_VCPUS · line 55
Quoted 2 lines
arch/arm/kvm/Kconfig +2
-0+config KVM_ARM_VGIC + bool "KVM support for Virtual GIC"Please indent with tab, as below.
fixed both, thanks.
cover KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Christoffer DallRenames the KVM_SET_DEVICE_ADDRESS to KVM_ARM_SET_DEVICE_ADDR to make it obvious that this is ARM specific in lack of a better generic interface.
Once we agree on a better interface the KVM/ARM code can also take advantage of that, but until then we don't want to hold up the KVM/ARM patches.
A new complete series of these patches including this change can be pulled from:
git://github.com/virtualopensystems/linux-kvm-arm.git
kvm-arm-v15-devaddr-v2
-Christoffer
---
Christoffer Dall (2):
KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
ARM: KVM: VGIC accept vcpu and dist base addresses from user space
Documentation/virtual/kvm/api.txt | 38 ++++++ arch/arm/include/asm/hardware/gic.h | 25 ++++ arch/arm/include/asm/kvm_host.h | 18 +++ arch/arm/include/asm/kvm_vgic.h | 89 +++++++++++++++ arch/arm/include/uapi/asm/kvm.h | 16 +++ arch/arm/kvm/Makefile | 1 arch/arm/kvm/arm.c | 92 +++++++++++++++- arch/arm/kvm/interrupts.S | 4 + arch/arm/kvm/mmio.c | 3 + arch/arm/kvm/vgic.c | 206 +++++++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 8 + 11 files changed, 498 insertions(+), 2 deletions(-) create mode 100644 arch/arm/include/asm/kvm_vgic.h create mode 100644 arch/arm/kvm/vgic.c
PATCH 1/2 KVM: ARM: Introduce KVM_SET_DEVICE_ADDRESS ioctl
On ARM (and possibly other architectures) 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 try to make this API slightly more generic than for our specific use, but so far only the VGIC uses this feature.
--- Documentation/virtual/kvm/api.txt | 37 +++++++++++++++++++++++++++++++++++++ arch/arm/include/uapi/asm/kvm.h | 13 +++++++++++++ arch/arm/kvm/arm.c | 23 ++++++++++++++++++++++- include/uapi/linux/kvm.h | 8 ++++++++ 4 files changed, 80 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +37 -0
@@ -2206,6 +2206,43 @@ 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 + +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 ------------------------
arch/arm/include/uapi/asm/kvm.h +13 -0
@@ -65,6 +65,19 @@ struct kvm_regs {#define KVM_ARM_TARGET_CORTEX_A15 0#define KVM_ARM_NUM_TARGETS 1 +/* KVM_SET_DEVICE_ADDRESS ioctl id encoding */ +#define KVM_DEVICE_TYPE_SHIFT 0 +#define KVM_DEVICE_TYPE_MASK (0xffff << KVM_DEVICE_TYPE_SHIFT) +#define KVM_DEVICE_ID_SHIFT 16 +#define KVM_DEVICE_ID_MASK (0xffff << KVM_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 +struct kvm_vcpu_init {__u32 target;__u32 features[7 ];
arch/arm/kvm/arm.c +22 -1
@@ -165,6 +165,8 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_COALESCED_MMIO : r =KVM_COALESCED_MMIO_PAGE_OFFSET ;break ; +case KVM_CAP_ARM_SET_DEVICE_ADDR : + r =1 ;case KVM_CAP_NR_VCPUS : r =num_online_cpus ();break ;
@@ -805,10 +807,29 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)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,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)
include/uapi/linux/kvm.h +8 -0
@@ -636,6 +636,7 @@ struct kvm_ppc_smmu_info {#define KVM_CAP_IRQFD_RESAMPLE 82#define KVM_CAP_PPC_BOOKE_WATCHDOG 83#define KVM_CAP_PPC_HTAB_FD 84 +#define KVM_CAP_ARM_SET_DEVICE_ADDR 85#ifdef KVM_CAP_IRQ_ROUTING
@@ -783,6 +784,11 @@ struct kvm_msi {__u8 pad[16 ]; }; +struct kvm_arm_device_addr { +__u64 id; +__u64 addr; +}; +/* * ioctls for VM fds */
@@ -868,6 +874,8 @@ struct kvm_s390_ucas_mapping {#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)/* Available with KVM_CAP_PPC_HTAB_FD */ #define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd) +/* Available with KVM_CAP_SET_DEVICE_ADDR */ +#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)/* * ioctls for vcpu fds
PATCH 2/2 ARM: KVM: VGIC accept vcpu and dist base addresses from user space
In reply to Christoffer DallUser space defines the model to emulate to a guest and should therefore decide which addresses are used for both the virtual CPU interface directly mapped in the guest physical address space and for the emulated distributor interface, which is mapped in software by the in-kernel VGIC support.
--- Documentation/virtual/kvm/api.txt | 1 + arch/arm/include/asm/kvm_vgic.h | 9 +++++ arch/arm/include/uapi/asm/kvm.h | 3 ++ arch/arm/kvm/arm.c | 14 ++++++++ arch/arm/kvm/vgic.c | 62 +++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 1 deletion(-)
Documentation/virtual/kvm/api.txt +1 -0
@@ -2218,6 +2218,7 @@ Errors: 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;
arch/arm/include/asm/kvm_vgic.h +9 -0
@@ -22,6 +22,9 @@#include <asm/hardware/gic.h> struct vgic_dist { +/* Distributor and vcpu interface mapping in the guest */ +phys_addr_t vgic_dist_base; +phys_addr_t vgic_cpu_base; };struct vgic_cpu {
@@ -33,6 +36,7 @@ struct kvm_run;struct kvm_exit_mmio ;#ifdef CONFIG_KVM_ARM_VGIC +int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr);bool vgic_handle_mmio (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_exit_mmio *mmio);
@@ -42,6 +46,11 @@ static inline int kvm_vgic_hyp_init(void)return 0 ; } +static inline int kvm_vgic_set_addr (struct kvm *kvm,unsigned long type,u64 addr) +{ +return 0 ; +} +static inline int kvm_vgic_init (struct kvm *kvm) {return 0 ;
arch/arm/include/uapi/asm/kvm.h +3 -0
@@ -78,6 +78,9 @@ struct kvm_regs {#define KVM_VGIC_V2_ADDR_TYPE_DIST 0#define KVM_VGIC_V2_ADDR_TYPE_CPU 1 +#define KVM_VGIC_V2_DIST_SIZE 0x1000 +#define KVM_VGIC_V2_CPU_SIZE 0x2000 +struct kvm_vcpu_init {__u32 target;__u32 features[7 ];
arch/arm/kvm/arm.c +13 -1
@@ -858,7 +858,19 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)static int kvm_vm_ioctl_set_device_addr (struct kvm *kvm,struct kvm_arm_device_addr *dev_addr) { -return -ENODEV ; +unsigned long dev_id, type; + + dev_id = (dev_addr->id &KVM_DEVICE_ID_MASK ) >>KVM_DEVICE_ID_SHIFT ; + type = (dev_addr->id &KVM_DEVICE_TYPE_MASK ) >>KVM_DEVICE_TYPE_SHIFT ; + +switch (dev_id) { +case KVM_ARM_DEVICE_VGIC_V2 : +if (!vgic_present) +return -ENXIO ; +return kvm_vgic_set_addr (kvm, type, dev_addr->addr); +default : +return -ENODEV ; + } } long kvm_arch_vm_ioctl(struct file *filp,
arch/arm/kvm/vgic.c +62 -0
71 lines not on this page · raw message
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Christoffer DallQuoted 7 lines · Christoffer Dall
Renames the
KVM_SET_DEVICE_ADDRESStoKVM_ARM_SET_DEVICE_ADDRto make it obvious that this is ARM specific in lack of a better generic interface.Once we agree on a better interface the KVM/ARM code can also take advantage of that, but until then we don't want to hold up the KVM/ARM patches.
Works for me. Scott, are you happy with this one too? We can start to introduce (and fix ARM) with a generic ioctl in the MPIC patches then.
Alex
Quoted 35 lines
A new complete series of these patches including this change can be pulled from:
git://github.com/virtualopensystems/linux-kvm-arm.git
kvm-arm-v15-devaddr-v2-Christoffer
---
Christoffer Dall (2):
KVM: ARM: IntroduceKVM_SET_DEVICE_ADDRESSioctl
ARM: KVM: VGIC accept vcpu and dist base addresses from user spaceDocumentation/virtual/kvm/api.txt | 38 ++++++ arch/arm/include/asm/hardware/gic.h | 25 ++++ arch/arm/include/asm/kvm_host.h | 18 +++ arch/arm/include/asm/kvm_vgic.h | 89 +++++++++++++++ arch/arm/include/uapi/asm/kvm.h | 16 +++ arch/arm/kvm/Makefile | 1 arch/arm/kvm/arm.c | 92 +++++++++++++++- arch/arm/kvm/interrupts.S | 4 + arch/arm/kvm/mmio.c | 3 + arch/arm/kvm/vgic.c | 206 +++++++++++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 8 + 11 files changed, 498 insertions(+), 2 deletions(-)create mode 100644
arch/arm/include/asm/kvm_vgic.hcreate mode 100644arch/arm/kvm/vgic.cSignature · 4 lines
_______________________________________________ kvmarm mailing list kvmarm at lists.cs.columbia.edu https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 6 lines · Alexander Graf
Quoted 2 lines · Christoffer Dall
Renames the
KVM_SET_DEVICE_ADDRESStoKVM_ARM_SET_DEVICE_ADDRto make it obvious that this is ARM specific in lack of a bettergeneric
Quoted 8 lines
Quoted 4 lines
interface.
Once we agree on a better interface the KVM/ARM code can also take advantage of that, but until then we don't want to hold up the
KVM/ARM
Quoted 1 line
patches.
Works for me. Scott, are you happy with this one too?
Not really, given that it will stay around forever even after something new is introduced.
If you're going to change the name, why not just change it to KVM_SET_DEVICE_CONFIG? Can we change the name later if nothing else changes (so it's still binary compatible)?
Quoted 2 lines
We can start to introduce (and fix ARM) with a generic ioctl in the MPIC patches then.
The ioctl is already generic, except for its name.
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 6 lines · Scott Wood
Quoted 5 lines · Alexander Graf
Quoted 4 lines · Christoffer Dall
Renames the
KVM_SET_DEVICE_ADDRESStoKVM_ARM_SET_DEVICE_ADDRto make it obvious that this is ARM specific in lack of a better generic interface.
Quoted 6 lines
Quoted 4 lines
Quoted 3 lines
Once we agree on a better interface the KVM/ARM code can also take advantage of that, but until then we don't want to hold up the KVM/ARM patches.
Works for me. Scott, are you happy with this one too?
Not really, given that it will stay around forever even after something new is introduced.
But only in ARM specific code.
Quoted 1 line
If you're going to change the name, why not just change it to
KVM_SET_DEVICE_CONFIG? Can we change the name later if nothing else changes (so it's still binary compatible)?
Because that again implies that it's generic enough. And to reach that conclusion will take more time than we should spend on this now.
Quoted 3 lines
Quoted 1 line
We can start to introduce (and fix ARM) with a generic ioctl in the MPIC patches then.
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64
* combining device id (variable) with addr type id (const) into a single field. It could just be split into multiple fields
* the id is 100% architecture specific. It shouldn't be. At least the "device id" field should be generic.
I'm not sure if we can come up with more problems in that API when staring at it a bit longer and/or we would actually start using it for more things. So for the sake of not holding up the ARM code, I'm perfectly fine to clutter ARM's ioctl handling code with an ioctl that is already deprecated at its introduction, as long as we don't hold everything else up meanwhile.
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 13 lines · Alexander Graf
Quoted 4 lines · Scott Wood
Quoted 3 lines · Alexander Graf
Quoted 2 lines · Christoffer Dall
Renames the
KVM_SET_DEVICE_ADDRESStoKVM_ARM_SET_DEVICE_ADDRto make it obvious that this is ARM specific in lack of a bettergeneric
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
interface.
Once we agree on a better interface the KVM/ARM code can also
take
Quoted 1 line
Quoted 1 line
Quoted 1 line
advantage of that, but until then we don't want to hold up the
Quoted 8 lines
KVM/ARM
Quoted 4 lines
Quoted 2 lines
Quoted 1 line
patches.
Works for me. Scott, are you happy with this one too?
Not really, given that it will stay around forever even after
something new is introduced.
But only in ARM specific code.
...which I'll probably have to deal with when Freescale's virtualization-capable ARM chips come along. I don't see "it's only in that other architecture" as "it might as well not exist".
Quoted 6 lines
Quoted 1 line
If you're going to change the name, why not just change it to
KVM_SET_DEVICE_CONFIG? Can we change the name later if nothing else changes (so it's still binary compatible)?Because that again implies that it's generic enough. And to reach that conclusion will take more time than we should spend on this now.
If the conclusion later on is that it is good enough, can the name be changed then?
Quoted 8 lines
Quoted 1 line
Quoted 1 line
We can start to introduce (and fix ARM) with a generic ioctl in
the MPIC patches then.
Quoted 2 lines
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64
This is tolerable IMHO.
Quoted 2 lines
* combining device id (variable) with addr type id (const) into a
single field. It could just be split into multiple fields
I agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Perhaps the threshold for an API becoming "permanent" should not be acceptance into the tree, but rather the removal of an "experimental" tag (including a way of shutting off experimental APIs to make sure you're not depending on them). Sort of like CONFIG_EXPERIMENTAL, except actually used for its intended purpose (distributions should have it *off* by default), and preferably managed at runtime. Sort of like drivers/staging, except for APIs rather than drivers. Changes at that point should require more justification than before merging, but would not have the strict compatibility requirement that non-experimental APIs have. This would make collaboration and testing easier on APIs that aren't ready to be permanent.
Quoted 2 lines
* the id is 100% architecture specific. It shouldn't be. At least
the "device id" field should be generic.
That's a documentation issue that could be changed to have all architectures adopt what is currently specified for ARM, without breaking compatibility.
Quoted 6 lines
I'm not sure if we can come up with more problems in that API when staring at it a bit longer and/or we would actually start using it for more things. So for the sake of not holding up the ARM code, I'm perfectly fine to clutter ARM's ioctl handling code with an ioctl that is already deprecated at its introduction, as long as we don't hold everything else up meanwhile.
I'm not in a position to block it, and if I were I presumably would have seen this in time for feedback to matter. That's different from actually being happy. :-)
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 11 lines · Alexander Graf
Quoted 10 lines · Scott Wood
Quoted 9 lines · Alexander Graf
Quoted 8 lines · Christoffer Dall
Quoted 7 lines
Renames the
KVM_SET_DEVICE_ADDRESStoKVM_ARM_SET_DEVICE_ADDRto make it obvious that this is ARM specific in lack of a better generic interface.Once we agree on a better interface the KVM/ARM code can also take advantage of that, but until then we don't want to hold up the KVM/ARM patches.
Quoted 6 lines
Quoted 4 lines
Quoted 3 lines
Quoted 1 line
Works for me. Scott, are you happy with this one too?
Not really, given that it will stay around forever even after something new is introduced.
But only in ARM specific code.
...which I'll probably have to deal with when Freescale's virtualization-capable ARM chips come along. I don't see "it's only in that other architecture" as "it might as well not exist".
I'm saying it's limiting its scope to a few lines of code in arch an arch specific file and makes everyone aware that we really need to come to a conclusion soon.
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
If you're going to change the name, why not just change it to
KVM_SET_DEVICE_CONFIG? Can we change the name later if nothing else changes (so it's still binary compatible)?Because that again implies that it's generic enough. And to reach that conclusion will take more time than we should spend on this now.
If the conclusion later on is that it is good enough, can the name be changed then?
We can add another generic name, yes. Changing it won't work because it'd break compatibility.
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
We can start to introduce (and fix ARM) with a generic ioctl in the MPIC patches then.
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64
Quoted 7 lines
This is tolerable IMHO.
Quoted 1 line
* combining device id (variable) with addr type id (const) into a single field. It could just be split into multiple fields
I agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Then we're the ones who have to come up with a good interface.
Quoted 2 lines
Perhaps the threshold for an API becoming "permanent" should not be acceptance into the tree, but rather the removal of an "experimental" tag (including a way of shutting off experimental APIs to make sure you're not depending on them). Sort of like
CONFIG_EXPERIMENTAL, except actually used for its intended purpose (distributions should have it *off* by default), and preferably managed at runtime. Sort of likedrivers/staging, except for APIs rather than drivers. Changes at that point should require more justification than before merging, but would not have the strict compatibility requirement that non-experimental APIs have. This would make collaboration and testing easier on APIs that aren't ready to be permanent.
This tag does exist. It's called "not in Linus' tree" :).
Quoted 4 lines
Quoted 2 lines
* the id is 100% architecture specific. It shouldn't be. At least the "device id" field should be generic.
That's a documentation issue that could be changed to have all architectures adopt what is currently specified for ARM, without breaking compatibility.
Depends on how we want to design the final layout. I don't have the impression that we've reached final conclusion on this interface. That's all I'm saying.
Quoted 4 lines
Quoted 2 lines
I'm not sure if we can come up with more problems in that API when staring at it a bit longer and/or we would actually start using it for more things. So for the sake of not holding up the ARM code, I'm perfectly fine to clutter ARM's ioctl handling code with an ioctl that is already deprecated at its introduction, as long as we don't hold everything else up meanwhile.
I'm not in a position to block it, and if I were I presumably would have seen this in time for feedback to matter. That's different from actually being happy. :-)
For the ARM specific ioctl it has my ack. I'd say let's go with that and start to work on a good interface ASAP. But we need an ok from Marcelo or Gleb too.
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 11 lines · Alexander Graf
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 1 line
I get that there's a tradeoff between getting something in now,
versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Then we're the ones who have to come up with a good interface.
How about another bad one, with PPC in the name, and some pleas to hurry things up? :-)
It's not as if there haven't been last-minute requests for API changes on the PPC side in the past...
Quoted 12 lines
Quoted 1 line
Perhaps the threshold for an API becoming "permanent" should not be
acceptance into the tree, but rather the removal of an "experimental" tag (including a way of shutting off experimental APIs to make sure you're not depending on them). Sort of like
CONFIG_EXPERIMENTAL, except actually used for its intended purpose (distributions should have it *off* by default), and preferably managed at runtime. Sort of likedrivers/staging, except for APIs rather than drivers. Changes at that point should require more justification than before merging, but would not have the strict compatibility requirement that non-experimental APIs have. This would make collaboration and testing easier on APIs that aren't ready to be permanent.
Quoted 1 line
This tag does exist. It's called "not in Linus' tree" :).
Which makes it a pain for multiple people to work on a new feature, especially when it spans components such as KVM and QEMU, and means that it gets less testing before the point of no return.
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 12 lines · Scott Wood
Quoted 11 lines · Alexander Graf
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 5 lines
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Quoted 10 lines
Quoted 1 line
Then we're the ones who have to come up with a good interface.
How about another bad one, with PPC in the name, and some pleas to hurry things up? :-)
It's not as if there haven't been last-minute requests for API changes on the PPC side in the past...
This is getting out of hand.
Do you have another API for PPC, which was send for review and not commented on several months ago that we can unify right now?
If not, let's go with the ARM name and work on the generic API in the mean time.
The end result will be something along 5 lines in a header files and 3 lines in a switch case that return -EINVAL if the interface is completely deprecated later on, which is not a big problem.
-Christoffer
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 26 lines · Christoffer Dall
Quoted 12 lines · Scott Wood
Quoted 11 lines · Alexander Graf
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 5 lines
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Quoted 10 lines
Quoted 1 line
Then we're the ones who have to come up with a good interface.
How about another bad one, with PPC in the name, and some pleas to hurry things up? :-)
It's not as if there haven't been last-minute requests for API changes on the PPC side in the past...
This is getting out of hand.
Quoted 8 lines
Do you have another API for PPC, which was send for review and not commented on several months ago that we can unify right now?
If not, let's go with the ARM name and work on the generic API in the mean time.
The end result will be something along 5 lines in a header files and 3 lines in a switch case that return
-EINVALif the interface is completely deprecated later on, which is not a big problem.
Agreed [1].
So what exactly are we waiting for? Acks from kvm maintainers, right?
Alex
[1] It'd probably end up being an ioctl that converts from one calling convention to another, resulting in maybe 5 lines in the switch case.
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 34 lines · Alexander Graf
Quoted 31 lines · Christoffer Dall
Quoted 12 lines · Scott Wood
Quoted 11 lines · Alexander Graf
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 5 lines
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Quoted 10 lines
Quoted 1 line
Then we're the ones who have to come up with a good interface.
How about another bad one, with PPC in the name, and some pleas to hurry things up? :-)
It's not as if there haven't been last-minute requests for API changes on the PPC side in the past...
This is getting out of hand.
Do you have another API for PPC, which was send for review and not commented on several months ago that we can unify right now?
If not, let's go with the ARM name and work on the generic API in the mean time.
Quoted 7 lines
Quoted 3 lines
The end result will be something along 5 lines in a header files and 3 lines in a switch case that return
-EINVALif the interface is completely deprecated later on, which is not a big problem.Agreed [1].
So what exactly are we waiting for? Acks from kvm maintainers, right?
In fact, we should probably CC them :)
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 41 lines · Alexander Graf
Quoted 38 lines · Alexander Graf
Quoted 34 lines · Christoffer Dall
Quoted 12 lines · Scott Wood
Quoted 11 lines · Alexander Graf
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 5 lines
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Quoted 10 lines
Quoted 1 line
Then we're the ones who have to come up with a good interface.
How about another bad one, with PPC in the name, and some pleas to hurry things up? :-)
It's not as if there haven't been last-minute requests for API changes on the PPC side in the past...
This is getting out of hand.
Do you have another API for PPC, which was send for review and not commented on several months ago that we can unify right now?
If not, let's go with the ARM name and work on the generic API in the mean time.
The end result will be something along 5 lines in a header files and 3 lines in a switch case that return
-EINVALif the interface is completely deprecated later on, which is not a big problem.
Quoted 7 lines
Quoted 3 lines
Agreed [1].
So what exactly are we waiting for? Acks from kvm maintainers, right?
In fact, we should probably CC them :)
I am looking at them right now :) Give me a couple of days please.
--
Gleb.
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Scott WoodQuoted 6 lines · Scott Wood
Quoted 3 lines · Alexander Graf
Am 09.01.2013 um 22:15 schrieb Scott Wood <[email protected]>:
Quoted 1 line
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Then we're the ones who have to come up with a good interface.
How about another bad one, with PPC in the name, and some pleas to hurry things up? :-)
Then I'd be the maintainer of that one and tell you whatever I think would be reasonable given the circumstances :).
Quoted 1 line
It's not as if there haven't been last-minute requests for API changes on the PPC side in the past...
I don't remember a full PPC target merge ever relying on an API change like this.
In fact, in this particular case one could merge all of the patches except for the particular ioctl implementation and just give the respective addresses default values until there is an API to set them, similar to how we did things with PVR in the beginning.
But this is something that's always up to the respective maintainers and I'm not going to interfere with how they do their job :).
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Perhaps the threshold for an API becoming "permanent" should not be acceptance into the tree, but rather the removal of an "experimental" tag (including a way of shutting off experimental APIs to make sure you're not depending on them). Sort of like
CONFIG_EXPERIMENTAL, except actually used for its intended purpose (distributions should have it *off* by default), and preferably managed at runtime. Sort of likedrivers/staging, except for APIs rather than drivers. Changes at that point should require more justification than before merging, but would not have the strict compatibility requirement that non-experimental APIs have. This would make collaboration and testing easier on APIs that aren't ready to be permanent.This tag does exist. It's called "not in Linus' tree" :).
Which makes it a pain for multiple people to work on a new feature, especially when it spans components such as KVM and QEMU, and means that it gets less testing before the point of no return.
I agree, but we're not going to solve this one now :). In fact, it'd be even harder to solve (with questionable results) than the actual ioctl in question.
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 4 lines · Alexander Graf
In fact, in this particular case one could merge all of the patches except for the particular ioctl implementation and just give the respective addresses default values until there is an API to set them, similar to how we did things with PVR in the beginning.
That's what we started with and we got review comments saying "yuck, don't hard code this"...
-- PMM
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Am 10.01.2013 um 11:17 schrieb Peter Maydell <[email protected]>:
Quoted 8 lines · Alexander Graf
Quoted 4 lines
In fact, in this particular case one could merge all of the patches except for the particular ioctl implementation and just give the respective addresses default values until there is an API to set them, similar to how we did things with PVR in the beginning.
That's what we started with and we got review comments saying "yuck, don't hard code this"...
And you shouldn't in the long run. But as an intermediate step, it's the best solution IMHO.
Either way, let's just finally get something in that doesn't clutter the global namespace :).
Alex
Quoted 2 lines
-- PMM
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Peter MaydellQuoted 11 lines · Peter Maydell
Quoted 7 lines · Alexander Graf
In fact, in this particular case one could merge all of the patches except for the
particular ioctl implementation and just give the respective addresses default
values until there is an API to set them, similar to how we did things with PVR
in the beginning.That's what we started with and we got review comments saying "yuck, don't hard code this"...
Even worse: hard-coding things breaks kvmtool (we do not emulate a vexpress and have a rather different memory map) and arm64 (the requirements on GIC mappings are different).
So hard coding addresses is already unacceptable.
M.
Signature · 1 line
Fast, cheap, reliable. Pick two.
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 11 lines · Marc Zyngier
Quoted 9 lines · Peter Maydell
Quoted 7 lines · Alexander Graf
In fact, in this particular case one could merge all of the patches except for the
particular ioctl implementation and just give the respective addresses default
values until there is an API to set them, similar to how we did things with PVR
in the beginning.
Quoted 8 lines
Quoted 2 lines
That's what we started with and we got review comments saying "yuck, don't hard code this"...
Even worse: hard-coding things breaks kvmtool (we do not emulate a vexpress and have a rather different memory map) and arm64 (the requirements on GIC mappings are different).
So hard coding addresses is already unacceptable.
I see. The current approach with an intermediate ARM specific ioctl is certainly good with me then. And who knows - with a bit of luck we might be able to get a unified ioctl model for this before the code hits Linus' tree (read: APIs are really stable).
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Alexander GrafQuoted 8 lines · Alexander Graf
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
We can start to introduce (and fix ARM) with a generic ioctl in the MPIC patches then.
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64
Quoted 7 lines
Quoted 7 lines
This is tolerable IMHO.
Quoted 1 line
* combining device id (variable) with addr type id (const) into a single field. It could just be split into multiple fields
I agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
As mentioned, i fail to see the benefit in sharing 0.0x% of the code (the interface), while the remaining code is not shared.
Quoted 1 line
Then we're the ones who have to come up with a good interface.
Or just have KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?
Quoted 26 lines
Quoted 2 lines
Perhaps the threshold for an API becoming "permanent" should not be acceptance into the tree, but rather the removal of an "experimental" tag (including a way of shutting off experimental APIs to make sure you're not depending on them). Sort of like
CONFIG_EXPERIMENTAL, except actually used for its intended purpose (distributions should have it *off* by default), and preferably managed at runtime. Sort of likedrivers/staging, except for APIs rather than drivers. Changes at that point should require more justification than before merging, but would not have the strict compatibility requirement that non-experimental APIs have. This would make collaboration and testing easier on APIs that aren't ready to be permanent.This tag does exist. It's called "not in Linus' tree" :).
Quoted 4 lines
Quoted 2 lines
* the id is 100% architecture specific. It shouldn't be. At least the "device id" field should be generic.
That's a documentation issue that could be changed to have all architectures adopt what is currently specified for ARM, without breaking compatibility.
Depends on how we want to design the final layout. I don't have the impression that we've reached final conclusion on this interface. That's all I'm saying.
Quoted 4 lines
Quoted 2 lines
I'm not sure if we can come up with more problems in that API when staring at it a bit longer and/or we would actually start using it for more things. So for the sake of not holding up the ARM code, I'm perfectly fine to clutter ARM's ioctl handling code with an ioctl that is already deprecated at its introduction, as long as we don't hold everything else up meanwhile.
I'm not in a position to block it, and if I were I presumably would have seen this in time for feedback to matter. That's different from actually being happy. :-)
For the ARM specific ioctl it has my ack. I'd say let's go with that and start to work on a good interface ASAP. But we need an ok from Marcelo or Gleb too.
Alex
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 18 lines · Marcelo Tosatti
Quoted 3 lines · Alexander Graf
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
We can start to introduce (and fix ARM) with a generic ioctl
in the MPIC patches then.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64This is tolerable IMHO.
Quoted 1 line
* combining device id (variable) with addr type id (const) into
a single field. It could just be split into multiple fields
Quoted 4 lines
Quoted 4 lines
I agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in now,
Quoted 8 lines
versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
As mentioned, i fail to see the benefit in sharing 0.0x% of the code (the
interface), while the remaining code is not shared.
Pointlessly making things architecture-specific just makes more work for people who later need the functionality on another architecture. It might not be much in this case (unless a particular device ends up being used on multiple architectures), but the principle still applies. It's also more work for tools like strace, and could get in the way of the userspace caller using common code.
Quoted 3 lines
Quoted 1 line
Then we're the ones who have to come up with a good interface.
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?
Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 36 lines · Scott Wood
Quoted 24 lines · Marcelo Tosatti
Quoted 3 lines · Alexander Graf
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
We can start to introduce (and fix ARM) with a generic
ioctl in the MPIC patches then.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64This is tolerable IMHO.
Quoted 1 line
* combining device id (variable) with addr type id (const)
into a single field. It could just be split into multiple fields
Quoted 4 lines
Quoted 4 lines
I agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in
now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Quoted 3 lines
As mentioned, i fail to see the benefit in sharing 0.0x% of the code (the
interface), while the remaining code is not shared.Pointlessly making things architecture-specific just makes more work for people who later need the functionality on another architecture. It might not be much in this case (unless a particular device ends up being used on multiple architectures), but the principle still applies. It's also more work for tools like strace, and could get in the way of the userspace caller using common code.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Then we're the ones who have to come up with a good interface.
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
I did not really grasp that ('shouldnt be specific to addresses'), but anyway.
OK, can you write down your proposed improvements to the interface? In case you have something ready, otherwise there is time pressure to merge the ARM port.
That is, if you have interest/energy to spend in a possibly reusable interface, as long as that does not delay integration of the ARM code, i don't think the ARM people will mind that.
As mentioned in the thread, they (ARM) require configurable device address.
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 5 lines · Marcelo Tosatti
Quoted 2 lines · Scott Wood
Quoted 1 line · Marcelo Tosatti
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside tothat?
Quoted 1 line
Quoted 7 lines
Quoted 4 lines
Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
I did not really grasp that ('shouldnt be specific to addresses'), but anyway.
A device may have other configuration parameters that need to be set, besides addresses. PPC MPIC will require information about the vendor and version, for example.
Quoted 3 lines
OK, can you write down your proposed improvements to the interface? In case you have something ready, otherwise there is time pressure to merge the ARM port.
My original request was just to change the name to something like KVM_SET_DEVICE_CONFIG or KVM_SET_DEVICE_ATTR, and not make the id encoding architecture-specific (preferably, separate into a "device id" field and an "attribute id" field rather than using bitfields). Actual values for device id could be architecture-specific (or there could be a global enumeration), and attribute id values would be device-specific.
Alex suggested that an ideal interface might accept values larger than 64
bits, though I think it's good enough -- there are currently no proposed uses that need more than 64 bits for a single attribute (unlike ONE_REG),
and if it is needed, such configuration could be split up between multiple attributes, or the attribute could specify that "value" be a userspace pointer to the actual data (as with ONE_REG).
Here's a writeup (the ARM details would go under ARM/vGIC-specific documentation):
4.80 KVM_SET_DEVICE_ATTR
Capability: KVM_CAP_SET_DEVICE_ATTR
Type: vm ioctl
Parameters: struct kvm_device_attr (in)
Returns: 0 on success, -1 on error
Errors:
ENODEV: The device id is unknown
ENXIO: Device not supported on current system
Other errors may be returned by specific devices and attributes.
struct kvm_device_attr {
__u32 device;
__u32 attr;
__u64 value;
};Specify an attribute of a device emulated or directly exposed by the kernel, which the host kernel needs to know about. The device field is an
architecture-specific identifier for a specific device. The attr field is a device-specific identifier for a specific attribute. Individual attributes may have particular requirements for when they can and cannot be set.
Quoted 3 lines
That is, if you have interest/energy to spend in a possibly reusable interface, as long as that does not delay integration of the ARM code, i don't think the ARM people will mind that.
The impression I've been given is that just about any change will delay the integration at this point. If that's the case, and everyone's OK with having an interface that is deprecated on arrival, then fine.
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 61 lines · Scott Wood
Quoted 10 lines · Marcelo Tosatti
Quoted 7 lines · Scott Wood
Quoted 1 line · Marcelo Tosatti
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
I did not really grasp that ('shouldnt be specific to addresses'), but anyway.
A device may have other configuration parameters that need to be set, besides addresses. PPC MPIC will require information about the vendor and version, for example.
Quoted 3 lines
OK, can you write down your proposed improvements to the interface? In case you have something ready, otherwise there is time pressure to merge the ARM port.
My original request was just to change the name to something like
KVM_SET_DEVICE_CONFIGorKVM_SET_DEVICE_ATTR, and not make the id encoding architecture-specific (preferably, separate into a "device id" field and an "attribute id" field rather than using bitfields). Actual values for device id could be architecture-specific (or there could be a global enumeration), and attribute id values would be device-specific.Alex suggested that an ideal interface might accept values larger than 64 bits, though I think it's good enough -- there are currently no proposed uses that need more than 64 bits for a single attribute (unlike
ONE_REG), and if it is needed, such configuration could be split up between multiple attributes, or the attribute could specify that "value" be a userspace pointer to the actual data (as withONE_REG).Here's a writeup (the ARM details would go under ARM/vGIC-specific documentation):
4.80
KVM_SET_DEVICE_ATTRCapability:
KVM_CAP_SET_DEVICE_ATTR
Type: vm ioctl
Parameters: structkvm_device_attr(in)
Returns: 0 on success, -1 on error
Errors:
ENODEV: The device id is unknown
ENXIO: Device not supported on current system
Other errors may be returned by specific devices and attributes.struct kvm_device_attr { __u32 device; __u32 attr; __u64 value; };Specify an attribute of a device emulated or directly exposed by the kernel, which the host kernel needs to know about. The device field is an architecture-specific identifier for a specific device. The attr field is a device-specific identifier for a specific attribute. Individual attributes may have particular requirements for when they can and cannot be set.
Quoted 7 lines
Quoted 3 lines
That is, if you have interest/energy to spend in a possibly reusable interface, as long as that does not delay integration of the ARM code, i don't think the ARM people will mind that.
The impression I've been given is that just about any change will delay the integration at this point. If that's the case, and everyone's OK with having an interface that is deprecated on arrival, then fine.
That is not entirely the case, but there wasn't event agreement on this revised API, and we didn't want to wait for weeks until a decision was made. Alex suggested we use a DEV_REG API similar to the ONE_REG API, but I am quite strongly against having such an API for this specific purpose as it is too semantically distant to what we do on ARM. (Having a DEV_REG API for other purposes might be fine though).
So I have no problem with your suggestion, although we could consider having a size and addr field in the struct instead and be slightly more extensible. But I don't feel strongly about it.
If we can agree on Scott's suggestion or with my modification (Alex, Gleb, Marcelo ?) then I'll change the KVM/ARM patches to use this and resend them right away. But we have to agree now!
If not, I really think we should keep things as they are now, as we're really discussing idealistic scenarios here, and the ARM patches have been out of tree for long enough. As Marcelo pointed out, the benefits of the perfect API are really minimal.
-Christoffer
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 74 lines · Christoffer Dall
Quoted 61 lines · Scott Wood
Quoted 10 lines · Marcelo Tosatti
Quoted 7 lines · Scott Wood
Quoted 1 line · Marcelo Tosatti
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
I did not really grasp that ('shouldnt be specific to addresses'), but anyway.
A device may have other configuration parameters that need to be set, besides addresses. PPC MPIC will require information about the vendor and version, for example.
Quoted 3 lines
OK, can you write down your proposed improvements to the interface? In case you have something ready, otherwise there is time pressure to merge the ARM port.
My original request was just to change the name to something like
KVM_SET_DEVICE_CONFIGorKVM_SET_DEVICE_ATTR, and not make the id encoding architecture-specific (preferably, separate into a "device id" field and an "attribute id" field rather than using bitfields). Actual values for device id could be architecture-specific (or there could be a global enumeration), and attribute id values would be device-specific.Alex suggested that an ideal interface might accept values larger than 64 bits, though I think it's good enough -- there are currently no proposed uses that need more than 64 bits for a single attribute (unlike
ONE_REG), and if it is needed, such configuration could be split up between multiple attributes, or the attribute could specify that "value" be a userspace pointer to the actual data (as withONE_REG).Here's a writeup (the ARM details would go under ARM/vGIC-specific documentation):
4.80
KVM_SET_DEVICE_ATTRCapability:
KVM_CAP_SET_DEVICE_ATTR
Type: vm ioctl
Parameters: structkvm_device_attr(in)
Returns: 0 on success, -1 on error
Errors:
ENODEV: The device id is unknown
ENXIO: Device not supported on current system
Other errors may be returned by specific devices and attributes.struct kvm_device_attr { __u32 device; __u32 attr; __u64 value; };Specify an attribute of a device emulated or directly exposed by the kernel, which the host kernel needs to know about. The device field is an architecture-specific identifier for a specific device. The attr field is a device-specific identifier for a specific attribute. Individual attributes may have particular requirements for when they can and cannot be set.
Quoted 7 lines
Quoted 3 lines
That is, if you have interest/energy to spend in a possibly reusable interface, as long as that does not delay integration of the ARM code, i don't think the ARM people will mind that.
The impression I've been given is that just about any change will delay the integration at this point. If that's the case, and everyone's OK with having an interface that is deprecated on arrival, then fine.
That is not entirely the case, but there wasn't event agreement on this revised API, and we didn't want to wait for weeks until a decision was made. Alex suggested we use a
DEV_REGAPI similar to theONE_REGAPI, but I am quite strongly against having such an API for this specific purpose as it is too semantically distant to what we do on ARM. (Having aDEV_REGAPI for other purposes might be fine though).
Quoted 7 lines
So I have no problem with your suggestion, although we could consider having a size and addr field in the struct instead and be slightly more extensible. But I don't feel strongly about it.
If we can agree on Scott's suggestion or with my modification (Alex, Gleb, Marcelo ?) then I'll change the KVM/ARM patches to use this and resend them right away. But we have to agree now!
If not, I really think we should keep things as they are now, as we're really discussing idealistic scenarios here, and the ARM patches have been out of tree for long enough. As Marcelo pointed out, the benefits of the perfect API are really minimal.
-Christoffer--
Can you make KVM_SET_ARM_DEVICE address extensible? Add some reserved space and a flags field.
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 77 lines · Marcelo Tosatti
Quoted 76 lines · Christoffer Dall
Quoted 61 lines · Scott Wood
Quoted 10 lines · Marcelo Tosatti
Quoted 7 lines · Scott Wood
Quoted 1 line · Marcelo Tosatti
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
I did not really grasp that ('shouldnt be specific to addresses'), but anyway.
A device may have other configuration parameters that need to be set, besides addresses. PPC MPIC will require information about the vendor and version, for example.
Quoted 3 lines
OK, can you write down your proposed improvements to the interface? In case you have something ready, otherwise there is time pressure to merge the ARM port.
My original request was just to change the name to something like
KVM_SET_DEVICE_CONFIGorKVM_SET_DEVICE_ATTR, and not make the id encoding architecture-specific (preferably, separate into a "device id" field and an "attribute id" field rather than using bitfields). Actual values for device id could be architecture-specific (or there could be a global enumeration), and attribute id values would be device-specific.Alex suggested that an ideal interface might accept values larger than 64 bits, though I think it's good enough -- there are currently no proposed uses that need more than 64 bits for a single attribute (unlike
ONE_REG), and if it is needed, such configuration could be split up between multiple attributes, or the attribute could specify that "value" be a userspace pointer to the actual data (as withONE_REG).Here's a writeup (the ARM details would go under ARM/vGIC-specific documentation):
4.80
KVM_SET_DEVICE_ATTRCapability:
KVM_CAP_SET_DEVICE_ATTR
Type: vm ioctl
Parameters: structkvm_device_attr(in)
Returns: 0 on success, -1 on error
Errors:ENODEV: The device id is unknown ENXIO: Device not supported on current systemOther errors may be returned by specific devices and attributes.
struct
kvm_device_attr{
__u32device;
__u32attr;
__u64value;
};Specify an attribute of a device emulated or directly exposed by the kernel, which the host kernel needs to know about. The device field is an architecture-specific identifier for a specific device. The attr field is a device-specific identifier for a specific attribute. Individual attributes may have particular requirements for when they can and cannot be set.
Quoted 7 lines
Quoted 3 lines
That is, if you have interest/energy to spend in a possibly reusable interface, as long as that does not delay integration of the ARM code, i don't think the ARM people will mind that.
The impression I've been given is that just about any change will delay the integration at this point. If that's the case, and everyone's OK with having an interface that is deprecated on arrival, then fine.
That is not entirely the case, but there wasn't event agreement on this revised API, and we didn't want to wait for weeks until a decision was made. Alex suggested we use a
DEV_REGAPI similar to theONE_REGAPI, but I am quite strongly against having such an API for this specific purpose as it is too semantically distant to what we do on ARM. (Having aDEV_REGAPI for other purposes might be fine though).So I have no problem with your suggestion, although we could consider having a size and addr field in the struct instead and be slightly more extensible. But I don't feel strongly about it.
Quoted 8 lines
Quoted 5 lines
If we can agree on Scott's suggestion or with my modification (Alex, Gleb, Marcelo ?) then I'll change the KVM/ARM patches to use this and resend them right away. But we have to agree now!
If not, I really think we should keep things as they are now, as we're really discussing idealistic scenarios here, and the ARM patches have been out of tree for long enough. As Marcelo pointed out, the benefits of the perfect API are really minimal.
-Christoffer--
Can you make
KVM_SET_ARM_DEVICEaddress extensible? Add some reserved space and a flags field.
Can't we do this for the new ioctl that we all would agree on rather than the interim one that's only a short term solution for a greater problem?
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 7 lines
Quoted 2 lines
Can you make
KVM_SET_ARM_DEVICEaddress extensible? Add some reserved space and a flags field.Can't we do this for the new ioctl that we all would agree on rather than the interim one that's only a short term solution for a greater problem?
Alex
OK.
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 10 lines · Marcelo Tosatti
Quoted 7 lines
Quoted 2 lines
Can you make
KVM_SET_ARM_DEVICEaddress extensible? Add some reserved space and a flags field.Can't we do this for the new ioctl that we all would agree on rather than the interim one that's only a short term solution for a greater problem?
Alex
OK.
Good. It's decided - the KVM/ARM patches remain in their current state with an ARM specific ioctl, and will transition to something generic post merge.
-Christoffer
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Scott WoodQuoted 48 lines · Scott Wood
Quoted 10 lines · Marcelo Tosatti
Quoted 7 lines · Scott Wood
Quoted 1 line · Marcelo Tosatti
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?Besides the above, and my original complaint that it shouldn't be specific to addresses?
-Scott
I did not really grasp that ('shouldnt be specific to addresses'), but anyway.
A device may have other configuration parameters that need to be set, besides addresses. PPC MPIC will require information about the vendor and version, for example.
Quoted 3 lines
OK, can you write down your proposed improvements to the interface? In case you have something ready, otherwise there is time pressure to merge the ARM port.
My original request was just to change the name to something like
KVM_SET_DEVICE_CONFIGorKVM_SET_DEVICE_ATTR, and not make the id encoding architecture-specific (preferably, separate into a "device id" field and an "attribute id" field rather than using bitfields). Actual values for device id could be architecture-specific (or there could be a global enumeration), and attribute id values would be device-specific.Alex suggested that an ideal interface might accept values larger than 64 bits, though I think it's good enough -- there are currently no proposed uses that need more than 64 bits for a single attribute (unlike
ONE_REG), and if it is needed, such configuration could be split up between multiple attributes, or the attribute could specify that "value" be a userspace pointer to the actual data (as withONE_REG).Here's a writeup (the ARM details would go under ARM/vGIC-specific documentation):
4.80
KVM_SET_DEVICE_ATTRCapability:
KVM_CAP_SET_DEVICE_ATTR
Type: vm ioctl
Parameters: structkvm_device_attr(in)
Returns: 0 on success, -1 on error
Errors:
ENODEV: The device id is unknown
ENXIO: Device not supported on current system
Other errors may be returned by specific devices and attributes.
Quoted 2 lines
struct kvm_device_attr {
__u32 device;This needs some semantic specification. Is device a constant value? Is it the return value of CREATE_IRQCHIP?
Quoted 11 lines
__u32 attr; __u64 value; };Specify an attribute of a device emulated or directly exposed by the kernel, which the host kernel needs to know about. The device field is an architecture-specific identifier for a specific device. The attr field is a device-specific identifier for a specific attribute. Individual attributes may have particular requirements for when they can and cannot be set.
Quoted 7 lines
Quoted 3 lines
That is, if you have interest/energy to spend in a possibly reusable interface, as long as that does not delay integration of the ARM code, i don't think the ARM people will mind that.
The impression I've been given is that just about any change will delay the integration at this point. If that's the case, and everyone's OK with having an interface that is deprecated on arrival, then fine.
To me it's perfectly fine to merge the patches with the arm specific interface and then push an interface like the above in in the next merge window.
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Quoted 8 lines · Alexander Graf
Quoted 2 lines · Scott Wood
struct kvm_device_attr { __u32 device;This needs some semantic specification. Is device a constant value? Is it the return value of
CREATE_IRQCHIP?
As proposed, it's up to the architecture to provide that specification. In theory this could be used for things other than IRQ chips. We could still say that device creation functions return a valid device ID (if the device has any attributes), as well as have other architecture-specific ways of describing device IDs (static enumeration). Or we could have non-architecture-specific static enumeration. Or just require that all devices be explicitly created by something that returns the ID.
Do you have a preferred approach?
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
Am 11.01.2013 um 21:11 schrieb Scott Wood <[email protected]>:
Quoted 9 lines · Alexander Graf
Quoted 4 lines · Scott Wood
Quoted 2 lines
struct kvm_device_attr { __u32 device;This needs some semantic specification. Is device a constant value? Is it the return value of
CREATE_IRQCHIP?As proposed, it's up to the architecture to provide that specification. In theory this could be used for things other than IRQ chips. We could still say that device creation functions return a valid device ID (if the device has any attributes), as well as have other architecture-specific ways of describing device IDs (static enumeration). Or we could have non-architecture-specific static enumeration. Or just require that all devices be explicitly created by something that returns the ID.
Do you have a preferred approach?
I am a fan of dynamically generated ids that get returned from the create functions (like open() and an fd).
I'm not sure if that would always work here though. It would mean that we explicitly have to create per-cpu interrupt controllers. Or append their state onto vcpu state.
Alex
Quoted 2 lines
-Scott
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Marcelo TosattiQuoted 11 lines · Marcelo Tosatti
Quoted 10 lines · Alexander Graf
Quoted 10 lines
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
We can start to introduce (and fix ARM) with a generic ioctl in the MPIC patches then.
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64This is tolerable IMHO.
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
Quoted 1 line
* combining device id (variable) with addr type id (const) into a single field. It could just be split into multiple fields
I agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
As mentioned, i fail to see the benefit in sharing 0.0x% of the code (the interface), while the remaining code is not shared.
Important code sharing happens in user space.
Quoted 4 lines
Quoted 2 lines
Then we're the ones who have to come up with a good interface.
Or just have
KVM_SET_PPC_DEVICE_ADDRESS. Is there a downside to that?
Yes. Harder to read code and a lack of commonality. Also it wouldn't cut it for us, as we need to set more than just addresses. But most of all I really hate to take a generic problem and solve it only for myself.
Btw, x86 has the same issue too, it just only somehow got away with not caring too much about it. The LAPIC has a version register that Mac OS X guests read. If the version is too old, it doesn't boot. So some time ago we just changed the version register.
The real, backwards compatible change however would've been to have user space tell us which version to emulate and set it accordingly. The way we did it basically broke backwards compatibility. We only got away with it because the register is rarely read.
Alex
Re: [kvmarm] [PATCH v5.1 0/2] KVM: ARM: Rename KVM_SET_DEVICE_ADDRESS
In reply to Scott WoodQuoted 18 lines · Scott Wood
Quoted 17 lines · Alexander Graf
Quoted 4 lines · Scott Wood
Quoted 3 lines · Alexander Graf
Quoted 2 lines · Christoffer Dall
Renames the
KVM_SET_DEVICE_ADDRESStoKVM_ARM_SET_DEVICE_ADDRto make it obvious that this is ARM specific in lack of abetter generic
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
interface.
Once we agree on a better interface the KVM/ARM code can also
take
Quoted 1 line
Quoted 1 line
Quoted 1 line
advantage of that, but until then we don't want to hold up
the KVM/ARM
Quoted 3 lines
Quoted 2 lines
Quoted 1 line
patches.
Works for me. Scott, are you happy with this one too?
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Not really, given that it will stay around forever even after
something new is introduced.
But only in ARM specific code.
...which I'll probably have to deal with when Freescale's virtualization-capable ARM chips come along. I don't see "it's only in that other architecture" as "it might as well not exist".
Doesnt it make sense to make it extensible by adding some reserved space and a flags field? (to the ioctl) (independently of anything else).
So that, say, supporting new ARM processors does not require adding a new ioctl?
Having a single ioctl does not increase code sharing significantly because large percentage of the code both in QEMU and the kernel are not shared (well perhaps except the interface).
Quoted 70 lines
Quoted 7 lines
Quoted 1 line
If you're going to change the name, why not just change it to
KVM_SET_DEVICE_CONFIG? Can we change the name later if nothing else changes (so it's still binary compatible)?Because that again implies that it's generic enough. And to reach that conclusion will take more time than we should spend on this now.
If the conclusion later on is that it is good enough, can the name be changed then?
Quoted 8 lines
Quoted 1 line
Quoted 1 line
We can start to introduce (and fix ARM) with a generic ioctl in
the MPIC patches then.
Quoted 2 lines
The ioctl is already generic, except for its name.
It's making a few wrong assumptions:
* maximum size of value is u64
This is tolerable IMHO.
Quoted 2 lines
* combining device id (variable) with addr type id (const) into
a single field. It could just be split into multiple fieldsI agree, but that could be lived with as well.
I get that there's a tradeoff between getting something in now, versus waiting until the API is more refined. Tagging it with a particular ISA seems like an odd way of saying "soon to be deprecated", though. What happens if we're still squabbling over the perfect replacement API when we're trying to push PPC MPIC stuff in?
Perhaps the threshold for an API becoming "permanent" should not be acceptance into the tree, but rather the removal of an "experimental" tag (including a way of shutting off experimental APIs to make sure you're not depending on them). Sort of like
CONFIG_EXPERIMENTAL, except actually used for its intended purpose (distributions should have it *off* by default), and preferably managed at runtime. Sort of likedrivers/staging, except for APIs rather than drivers. Changes at that point should require more justification than before merging, but would not have the strict compatibility requirement that non-experimental APIs have. This would make collaboration and testing easier on APIs that aren't ready to be permanent.Quoted 2 lines
* the id is 100% architecture specific. It shouldn't be. At
least the "device id" field should be generic.That's a documentation issue that could be changed to have all architectures adopt what is currently specified for ARM, without breaking compatibility.
Quoted 6 lines
I'm not sure if we can come up with more problems in that API when staring at it a bit longer and/or we would actually start using it for more things. So for the sake of not holding up the ARM code, I'm perfectly fine to clutter ARM's ioctl handling code with an ioctl that is already deprecated at its introduction, as long as we don't hold everything else up meanwhile.
I'm not in a position to block it, and if I were I presumably would have seen this in time for feedback to matter. That's different from actually being happy. :-)
-Scott
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html