Re: [PATCH 2/4] kvmtool: ARM: allow level interrupts in device tree

2014-12-12 Thread Andre Przywara
Hi,

On 11/12/14 17:15, Will Deacon wrote:
 On Thu, Dec 11, 2014 at 04:30:33PM +, Andre Przywara wrote:
 Currently we describe every interrupt for each device in the FDT
 as being edge triggered.
 Add a parameter to the irq property generation to allow devices to
 specify their interrupts as level triggered if needed.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  tools/kvm/arm/fdt.c|6 +++---
  tools/kvm/hw/serial.c  |5 +++--
  tools/kvm/include/kvm/ioport.h |4 +++-
  tools/kvm/ioport.c |6 --
  tools/kvm/virtio/mmio.c|5 +++--
  5 files changed, 16 insertions(+), 10 deletions(-)
 
 [...]
 
 @@ -71,7 +72,8 @@ static void generate_ioport_fdt_node(void *fdt,
  static void generate_ioport_fdt_node(void *fdt,
   struct device_header *dev_hdr,
   void (*generate_irq_prop)(void *fdt,
 -   u8 irq))
 +   u8 irq,
 +   u32 irq_type))
  {
  die(Unable to generate device tree nodes without libfdt\n);
  }
 diff --git a/tools/kvm/virtio/mmio.c b/tools/kvm/virtio/mmio.c
 index 3a2bd62..28b0651 100644
 --- a/tools/kvm/virtio/mmio.c
 +++ b/tools/kvm/virtio/mmio.c
 @@ -233,7 +233,8 @@ static void virtio_mmio_mmio_callback(struct kvm_cpu 
 *vcpu,
  static void generate_virtio_mmio_fdt_node(void *fdt,
struct device_header *dev_hdr,
void (*generate_irq_prop)(void *fdt,
 -u8 irq))
 +u8 irq,
 +u32 type))
  {
  char dev_name[DEVICE_NAME_MAX_LEN];
  struct virtio_mmio *vmmio = container_of(dev_hdr,
 @@ -250,7 +251,7 @@ static void generate_virtio_mmio_fdt_node(void *fdt,
  _FDT(fdt_begin_node(fdt, dev_name));
  _FDT(fdt_property_string(fdt, compatible, virtio,mmio));
  _FDT(fdt_property(fdt, reg, reg_prop, sizeof(reg_prop)));
 -generate_irq_prop(fdt, vmmio-irq);
 +generate_irq_prop(fdt, vmmio-irq, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
 
 This is a GIC-specific #define in arch-agnostic code. I think we should have
 a new enum type for describing edge and level interrupts, then just use
 that instead.

Right, good point.
I dug a bit in the kernel source, and actually those values behind the
defines are not GIC specific, but are generic IRQ FDT values (used by
other architectures as well). Even the GIC driver source uses these
defines, it's just the GICv3 binding doc that speaks of those specific
numbers.
So if you don't mind, I will remove the GIC_FDT_IRQ_FLAGS_{LEVEL,EDGE}
defines from kvmtool's headers and use the generic defines from the
kernel in one of the fdt headers.

Cheers,
Andre.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/4] kvmtool: remove warning about bzImage on non-x86 architectures

2014-12-11 Thread Andre Przywara
Among the architectures supported by kvmtool, only x86 defines a
bzImage format. So we shouldn't bother users of other architectures
with a message about something that cannot work.
Make the bzImage check dependent on compiling for x86.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/kvm.c |5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
index e1b9f6c..21817c3 100644
--- a/tools/kvm/kvm.c
+++ b/tools/kvm/kvm.c
@@ -380,12 +380,15 @@ bool kvm__load_kernel(struct kvm *kvm, const char 
*kernel_filename,
die(%s is not an initrd, initrd_filename);
}
 
+#ifdef CONFIG_X86
ret = load_bzimage(kvm, fd_kernel, fd_initrd, kernel_cmdline);
 
if (ret)
goto found_kernel;
 
-   pr_warning(%s is not a bzImage. Trying to load it as a flat 
binary..., kernel_filename);
+   pr_warning(%s is not a bzImage. Trying to load it as an ELF or flat 
binary...,
+  kernel_filename);
+#endif
 
ret = load_elf_binary(kvm, fd_kernel, fd_initrd, kernel_cmdline);
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/4] kvmtool: ARM: allow level interrupts in device tree

2014-12-11 Thread Andre Przywara
Currently we describe every interrupt for each device in the FDT
as being edge triggered.
Add a parameter to the irq property generation to allow devices to
specify their interrupts as level triggered if needed.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/arm/fdt.c|6 +++---
 tools/kvm/hw/serial.c  |5 +++--
 tools/kvm/include/kvm/ioport.h |4 +++-
 tools/kvm/ioport.c |6 --
 tools/kvm/virtio/mmio.c|5 +++--
 5 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c
index 4a33846..918d89f 100644
--- a/tools/kvm/arm/fdt.c
+++ b/tools/kvm/arm/fdt.c
@@ -74,12 +74,12 @@ static void generate_cpu_nodes(void *fdt, struct kvm *kvm)
_FDT(fdt_end_node(fdt));
 }
 
-static void generate_irq_prop(void *fdt, u8 irq)
+static void generate_irq_prop(void *fdt, u8 irq, u32 irq_type)
 {
u32 irq_prop[] = {
cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI),
cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE),
-   cpu_to_fdt32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI),
+   cpu_to_fdt32(irq_type)
};
 
_FDT(fdt_property(fdt, interrupts, irq_prop, sizeof(irq_prop)));
@@ -127,7 +127,7 @@ static int setup_fdt(struct kvm *kvm)
void *fdt_dest  = guest_flat_to_host(kvm,
 kvm-arch.dtb_guest_start);
void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
-   void (*)(void *, u8));
+   void (*)(void *, u8, u32));
void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *, u32)
= kvm-cpus[0]-generate_fdt_nodes;
 
diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
index 60147de..266863b 100644
--- a/tools/kvm/hw/serial.c
+++ b/tools/kvm/hw/serial.c
@@ -369,7 +369,8 @@ static bool serial8250_in(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 port,
 #define DEVICE_NAME_MAX_LEN 32
 static void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
 void (*generate_irq_prop)(void *fdt,
-  u8 irq))
+  u8 irq,
+  u32 type))
 {
char dev_name[DEVICE_NAME_MAX_LEN];
struct serial8250_device *dev = ioport-priv;
@@ -384,7 +385,7 @@ static void serial8250_generate_fdt_node(struct ioport 
*ioport, void *fdt,
_FDT(fdt_begin_node(fdt, dev_name));
_FDT(fdt_property_string(fdt, compatible, ns16550a));
_FDT(fdt_property(fdt, reg, reg_prop, sizeof(reg_prop)));
-   generate_irq_prop(fdt, dev-irq);
+   generate_irq_prop(fdt, dev-irq, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
_FDT(fdt_property_cell(fdt, clock-frequency, 1843200));
_FDT(fdt_end_node(fdt));
 }
diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
index 18da47c..ffd938d 100644
--- a/tools/kvm/include/kvm/ioport.h
+++ b/tools/kvm/include/kvm/ioport.h
@@ -31,7 +31,9 @@ struct ioport_operations {
bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
void (*generate_fdt_node)(struct ioport *ioport, void *fdt,
- void (*generate_irq_prop)(void *fdt, u8 irq));
+ void (*generate_irq_prop)(void *fdt,
+   u8 irq,
+   u32 irq_type));
 };
 
 void ioport__setup_arch(struct kvm *kvm);
diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
index 5bfb7e2..b507cab 100644
--- a/tools/kvm/ioport.c
+++ b/tools/kvm/ioport.c
@@ -59,7 +59,8 @@ static void ioport_remove(struct rb_root *root, struct ioport 
*data)
 static void generate_ioport_fdt_node(void *fdt,
 struct device_header *dev_hdr,
 void (*generate_irq_prop)(void *fdt,
-  u8 irq))
+  u8 irq,
+  u32 irq_type))
 {
struct ioport *ioport = container_of(dev_hdr, struct ioport, dev_hdr);
struct ioport_operations *ops = ioport-ops;
@@ -71,7 +72,8 @@ static void generate_ioport_fdt_node(void *fdt,
 static void generate_ioport_fdt_node(void *fdt,
 struct device_header *dev_hdr,
 void (*generate_irq_prop)(void *fdt,
-  u8 irq

[PATCH 3/4] kvmtool: ARM: advertise 8250 IRQs as level-triggered

2014-12-11 Thread Andre Przywara
Both the 16550/8250 UART emulation in kvmtool as well as all the
drivers and DTBs for real hardware use level triggered interrupts.
But the device tree currently describes them as being edge triggered,
which can lead to hangs in guests.
Use the new IRQ type parameter to properly describe the interrupts.
This goes along the lines of a similar QEMU patch:
http://git.qemu.org/?p=qemu.git;a=commitdiff;h=0be969a2d974971628fc4ed95834d22ecf0fd497

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/hw/serial.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
index 266863b..f223802 100644
--- a/tools/kvm/hw/serial.c
+++ b/tools/kvm/hw/serial.c
@@ -385,7 +385,7 @@ static void serial8250_generate_fdt_node(struct ioport 
*ioport, void *fdt,
_FDT(fdt_begin_node(fdt, dev_name));
_FDT(fdt_property_string(fdt, compatible, ns16550a));
_FDT(fdt_property(fdt, reg, reg_prop, sizeof(reg_prop)));
-   generate_irq_prop(fdt, dev-irq, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
+   generate_irq_prop(fdt, dev-irq, GIC_FDT_IRQ_FLAGS_LEVEL_HI);
_FDT(fdt_property_cell(fdt, clock-frequency, 1843200));
_FDT(fdt_end_node(fdt));
 }
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] kvmtool: ARM: fix initrd functionality

2014-12-11 Thread Andre Przywara
lkvm -i is currently broken on ARM/ARM64.
We should not try to convert smaller-than-4GB addresses into 64-bit
big endian and then stuff them into u32 variables if we expect to read
anything other than 0 out of it.
Adjust the type to u64 to write the proper address in BE format into
the /chosen node (and also match the address size we formely posted)
and let Linux thus read the right values.
This fixes initrd functionality for ARM and ARM64 guests.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
Acked-by: Marc Zyngier marc.zyng...@arm.com
---
 tools/kvm/arm/fdt.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c
index 5626931..4a33846 100644
--- a/tools/kvm/arm/fdt.c
+++ b/tools/kvm/arm/fdt.c
@@ -149,8 +149,8 @@ static int setup_fdt(struct kvm *kvm)
 
/* Initrd */
if (kvm-arch.initrd_size != 0) {
-   u32 ird_st_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start);
-   u32 ird_end_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start +
+   u64 ird_st_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start);
+   u64 ird_end_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start +
   kvm-arch.initrd_size);
 
_FDT(fdt_property(fdt, linux,initrd-start,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/4] kvmtool: ARM: fixing initrd, serial IRQs and bzImage message

2014-12-11 Thread Andre Przywara
Hi,

dumping a part of my kvmtool patch queue here.

Patch 1 (fixing initrd for ARM) was already on the list, but hasn't
been merged yet.
Patch 2 and 3 let kvmtool describe the 8250 serial IRQs as level
triggered and fix a stability problem.
Patch 4 is an easy fix for a message that annoys me every time ;-)

Cheers,
Andre.

Andre Przywara (4):
  kvmtool: ARM: fix initrd functionality
  kvmtool: ARM: allow level interrupts in device tree
  kvmtool: ARM: advertise 8250 IRQs as level-triggered
  kvmtool: remove warning about bzImage on non-x86 architectures

 tools/kvm/arm/fdt.c|   10 +-
 tools/kvm/hw/serial.c  |5 +++--
 tools/kvm/include/kvm/ioport.h |4 +++-
 tools/kvm/ioport.c |6 --
 tools/kvm/kvm.c|5 -
 tools/kvm/virtio/mmio.c|5 +++--
 6 files changed, 22 insertions(+), 13 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] arm/arm64: vgic: Remove unreachable irq_clear_pending

2014-11-24 Thread Andre Przywara
Hej Christoffer,

On 24/11/14 09:41, Christoffer Dall wrote:
 When 'injecting' an edge-triggered interrupt with a falling edge we
 shouldn't clear the pending state on the distributor.  In fact, we
 don't, because the check in vgic_validate_injection would prevent us
 from ever reaching this bit of code.
 
 Remove the unreachable snippet.
 
 Signed-off-by: Christoffer Dall christoffer.d...@linaro.org

Acked-by: Andre Przywara andre.przyw...@arm.com

I agree on this. Would it make sense to rewrite this function a bit to
make it more clearer what happens? I find the nesting of the
if-statements counter-intuitive: I'd prefer to first differentiate
between level and edge triggered and then only check the actual level in
the level-triggered branch. Not sure if it's worth the fuss, though.

Cheers,
Andre.

 ---
  virt/kvm/arm/vgic.c | 2 --
  1 file changed, 2 deletions(-)
 
 diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
 index 3aaca49..f45cf16 100644
 --- a/virt/kvm/arm/vgic.c
 +++ b/virt/kvm/arm/vgic.c
 @@ -1643,8 +1643,6 @@ static bool vgic_update_irq_pending(struct kvm *kvm, 
 int cpuid,
   vgic_dist_irq_clear_level(vcpu, irq_num);
   if (!vgic_dist_irq_soft_pend(vcpu, irq_num))
   vgic_dist_irq_clear_pending(vcpu, irq_num);
 - } else {
 - vgic_dist_irq_clear_pending(vcpu, irq_num);
   }
   }
  
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 0/3] irqfd support for arm/arm64

2014-11-24 Thread Andre Przywara
Hi,

On 24/11/14 10:10, Eric Auger wrote:
 On 11/24/2014 10:47 AM, Christoffer Dall wrote:
 On Sun, Nov 23, 2014 at 06:56:57PM +0100, Eric Auger wrote:
 This patch series enables irqfd on arm and arm64.

 Irqfd framework enables to inject a virtual IRQ into a guest upon an
 eventfd trigger. User-side uses KVM_IRQFD VM ioctl to provide KVM with
 a kvm_irqfd struct that associates a VM, an eventfd, a virtual IRQ number
 (aka. the gsi). When an actor signals the eventfd (typically a VFIO
 platform driver), the kvm irqfd subsystem injects the gsi into the VM.

 Resamplefd also is supported for level sensitive interrupts, ie. the
 user can provide another eventfd that is triggered when the completion
 of the virtual IRQ (gsi) is detected by the GIC.

 The gsi must correspond to a shared peripheral interrupt (SPI), ie the
 GIC interrupt ID is gsi + 32.

 The rationale behind not supporting PPI irqfd injection is that
 any device using a PPI would be a private-to-the-CPU device (timer for
 instance), so its state would have to be context-switched along with the
 VCPU and would require in-kernel wiring anyhow. It is not a relevant use
 case for irqfds.

 this patch enables CONFIG_HAVE_KVM_EVENTFD and CONFIG_HAVE_KVM_IRQFD.

 No IRQ routing table is used, enabling to remove CONFIG_HAVE_KVM_IRQCHIP

 can be found at git://git.linaro.org/people/eric.auger/linux.git
 on branch irqfd_integ_v8

 This work was tested with Calxeda Midway xgmac main interrupt with
 qemu-system-arm and QEMU VFIO platform device. Also irqfd was proven
 functional on several vhost-net prototypes.

 v3 - v4:
 - rebase on 3.18rc5
 - vgic dynamic instantiation brought new challenges:
   handling of irqfd injection when vgic is not ready
 - unset of CONFIG_HAVE_KVM_IRQCHIP in a separate patch
 - add arm64 enable
 - vgic.c style modifications according to Christoffer comments


 There also seems to be a different split of the patches here?
 Hi Christoffer,
 yes I added arm64b support and moved CONFIG_HAVE_KVM_IRQCHIP removal in
 a separate patch.

 We've probably also reached the point where you need to start rebasing
 on Andre's GICv3 patches, which I expect will go in first.
 the patch applies without conflict on Andre's series.

Yes, I can confirm this. I also manually checked the patches to spot any
fallouts due to the vgic.c file split, but Eric's patches are not
affected by this.

Cheers,
Andre.

 
 BR
 
 Eric

 Thanks,
 -Christoffer

 
 ___
 kvmarm mailing list
 kvm...@lists.cs.columbia.edu
 https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 1/4] ARM: KVM: on unhandled IO mem abort, route the call to the KVM MMIO bus

2014-11-13 Thread Andre Przywara
Hi Nikolay,

On 13/11/14 11:37, Marc Zyngier wrote:
 [fixing Andre's email address]
 
 On 13/11/14 11:20, Christoffer Dall wrote:
 On Thu, Nov 13, 2014 at 12:45:42PM +0200, Nikolay Nikolaev wrote:

 [...]


 Going through the vgic_handle_mmio we see that it will require large
 refactoring:
  - there are 15 MMIO ranges for the vgic now - each should be
 registered as a separate device
  - the handler of each range should be split into read and write
  - all handlers take 'struct kvm_exit_mmio', and pass it to
 'vgic_reg_access', 'mmio_data_read' and 'mmio_data_read'

 To sum up - if we do this refactoring of vgic's MMIO handling +
 kvm_io_bus_ API getting 'vcpu argument we'll get a 'much' cleaner
 vgic code and as a bonus we'll get 'ioeventfd' capabilities.

 We have 3 questions:
  - is the kvm_io_bus_ getting 'vcpu' argument acceptable for the other
 architectures too?
  - is this huge vgic MMIO handling redesign acceptable/desired (it
 touches a lot of code)?
  - is there a way that ioeventfd is accepted leaving vgic.c in it's
 current state?

 Not sure how the latter question is relevant to this, but check with
 Andre who recently looked at this as well and decided that for GICv3 the
 only sane thing was to remove that comment for the gic.
 @Andre - what's your experience with the GICv3 and MMIO handling,
 anything specific?

 I don't recall the details of what you were trying to accomplish here
 (it's been 8 months or so) but the surely the vgic handling code should
 *somehow* be integrated into the handle_kernel_mmio (like Paolo
 suggested), unless you come back and tell me that that would involve a
 complete rewrite of the vgic code.
 I'm experimenting now - it's not exactly rewrite of whole vgic code,
 but it will touch a lot of it  - all MMIO access handlers and the
 supporting functions.
 We're ready to spend the effort. My question is  - is this acceptable?

 I certainly appreciate the offer to do this work, but it's hard to say
 at this point if it is worth it.

 What I was trying to say above is that Andre looked at this, and came to
 the conclusion that it is not worth it.

 Marc, what are your thoughts?
 
 Same here, I rely on Andre's view that it was not very useful. Now, it
 would be good to see a mock-up of the patches and find out:

Seconded, can you send a pointer to the VGIC rework patches mentioned?

 - if it is a major improvement for the general quality of the code
 - if that allow us to *delete* a lot of code (if it is just churn, I'm
 not really interested)
 - if it helps or hinders further developments that are currently in the
 pipeline
 
 Andre, can you please share your findings? I don't remember the
 specifics of the discussion we had a few months ago...

1) Given the date in the reply I sense that your patches are from March
this year or earlier. So this is based on VGIC code from March, which
predates Marc's vgic_dyn changes that just went in 3.18-rc1? His patches
introduced another member to struct mmio_range to check validity of
accesses with a reduced number of SPIs supported (.bits_per_irq).
So is this covered in your rework?

2)
  - there are 15 MMIO ranges for the vgic now - each should be

Well, the GICv3 emulation adds 41 new ranges. Not sure if this still fits.

 registered as a separate device

I found this fact a show-stopper when looking at this a month ago.
Somehow it feels wrong to register a bunch of pseudo-devices. I could go
with registering a small number of regions (one distributor, two
redistributor regions for instance), but not handling every single of
the 41 + 15 register groups as a device.

Also I wasn't sure if we had to expose some of the vGIC structures to
the other KVM code layers.

But I am open to any suggestions (as long as they go in _after_ my
vGICv3 series ;-)  - so looking forward to some repo to see how it looks
like.

Cheers,
Andre.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 1/4] ARM: KVM: on unhandled IO mem abort, route the call to the KVM MMIO bus

2014-11-13 Thread Andre Przywara
Hi Nikolay,

On 13/11/14 12:29, Nikolay Nikolaev wrote:
 On Thu, Nov 13, 2014 at 1:52 PM, Andre Przywara andre.przyw...@arm.com 
 wrote:
 Hi Nikolay,

 On 13/11/14 11:37, Marc Zyngier wrote:
 [fixing Andre's email address]

 On 13/11/14 11:20, Christoffer Dall wrote:
 On Thu, Nov 13, 2014 at 12:45:42PM +0200, Nikolay Nikolaev wrote:

 [...]


 Going through the vgic_handle_mmio we see that it will require large
 refactoring:
  - there are 15 MMIO ranges for the vgic now - each should be
 registered as a separate device
  - the handler of each range should be split into read and write
  - all handlers take 'struct kvm_exit_mmio', and pass it to
 'vgic_reg_access', 'mmio_data_read' and 'mmio_data_read'

 To sum up - if we do this refactoring of vgic's MMIO handling +
 kvm_io_bus_ API getting 'vcpu argument we'll get a 'much' cleaner
 vgic code and as a bonus we'll get 'ioeventfd' capabilities.

 We have 3 questions:
  - is the kvm_io_bus_ getting 'vcpu' argument acceptable for the other
 architectures too?
  - is this huge vgic MMIO handling redesign acceptable/desired (it
 touches a lot of code)?
  - is there a way that ioeventfd is accepted leaving vgic.c in it's
 current state?

 Not sure how the latter question is relevant to this, but check with
 Andre who recently looked at this as well and decided that for GICv3 the
 only sane thing was to remove that comment for the gic.
 @Andre - what's your experience with the GICv3 and MMIO handling,
 anything specific?

 I don't recall the details of what you were trying to accomplish here
 (it's been 8 months or so) but the surely the vgic handling code should
 *somehow* be integrated into the handle_kernel_mmio (like Paolo
 suggested), unless you come back and tell me that that would involve a
 complete rewrite of the vgic code.
 I'm experimenting now - it's not exactly rewrite of whole vgic code,
 but it will touch a lot of it  - all MMIO access handlers and the
 supporting functions.
 We're ready to spend the effort. My question is  - is this acceptable?

 I certainly appreciate the offer to do this work, but it's hard to say
 at this point if it is worth it.

 What I was trying to say above is that Andre looked at this, and came to
 the conclusion that it is not worth it.

 Marc, what are your thoughts?

 Same here, I rely on Andre's view that it was not very useful. Now, it
 would be good to see a mock-up of the patches and find out:

 Seconded, can you send a pointer to the VGIC rework patches mentioned?
 They are still in WiP state - not exactly working. I'm still exploring
 what the status is.
 
 Our major target is having ioeventfd suport in ARM. For this we need
 to support kvm_io_bus_ mechanisms for MMIO access (cause ioevent fd
 device is registered this way). Then this subject of integrating vgic
 with the kvm_io_bus_ APIs came up.
 My personal opinion - they should be able to coexist in peace.
 

 - if it is a major improvement for the general quality of the code
 - if that allow us to *delete* a lot of code (if it is just churn, I'm
 not really interested)
 - if it helps or hinders further developments that are currently in the
 pipeline

 Andre, can you please share your findings? I don't remember the
 specifics of the discussion we had a few months ago...

 1) Given the date in the reply I sense that your patches are from March
 this year or earlier. So this is based on VGIC code from March, which
 predates Marc's vgic_dyn changes that just went in 3.18-rc1? His patches
 introduced another member to struct mmio_range to check validity of
 accesses with a reduced number of SPIs supported (.bits_per_irq).
 So is this covered in your rework?
 Still no (rebased to 3.17) - didn't see it, but should not be an issue.

 2)
  - there are 15 MMIO ranges for the vgic now - each should be

 Well, the GICv3 emulation adds 41 new ranges. Not sure if this still fits.

 registered as a separate device

 I found this fact a show-stopper when looking at this a month ago.
 Somehow it feels wrong to register a bunch of pseudo-devices. I could go
 with registering a small number of regions (one distributor, two
 redistributor regions for instance), but not handling every single of
 the 41 + 15 register groups as a device.
 Do you sense performance issues, or just it's not right?

Just not right, since they are no 15 devices for a GICv2 emulation.

 Maybe kvm_io_bus_ needs some extesion to hanlde a device with multiple 
 regions?

Well, maybe a simple rename could fix this, but I am not sure it still
fits then. I am just afraid we end up with quite some code duplication
in each handler function. Also if we needed to split-up read and write
this ends up with much more code. Currently this is cleverly handled in
one function without looking messy (great job, Marc, btw!)

Also handling private GICv3 interrupts is no longer done via a single
MMIO offset banked by the accessing (v)CPU, but by per-CPU MMIO regions.
Would we need to register separate devices for each VCPU

Re: [RFC PATCH 1/4] ARM: KVM: on unhandled IO mem abort, route the call to the KVM MMIO bus

2014-11-13 Thread Andre Przywara


On 13/11/14 15:02, Nikolay Nikolaev wrote:
 On Thu, Nov 13, 2014 at 4:23 PM, Eric Auger eric.au...@linaro.org wrote:
 On 11/13/2014 03:16 PM, Eric Auger wrote:
 On 11/13/2014 11:45 AM, Nikolay Nikolaev wrote:
 On Mon, Nov 10, 2014 at 6:27 PM, Christoffer Dall
 christoffer.d...@linaro.org wrote:
 On Mon, Nov 10, 2014 at 05:09:07PM +0200, Nikolay Nikolaev wrote:
 Hello,

 On Fri, Mar 28, 2014 at 9:09 PM, Christoffer Dall
 christoffer.d...@linaro.org wrote:

 On Thu, Mar 13, 2014 at 04:57:26PM +0100, Antonios Motakis wrote:
 On an unhandled IO memory abort, use the kvm_io_bus_* API in order to
 handle the MMIO access through any registered read/write callbacks. 
 This
 is a dependency for eventfd support (ioeventfd and irqfd).

 However, accesses to the VGIC are still left implemented independently,
 since the kvm_io_bus_* API doesn't pass the VCPU pointer doing the 
 access.

 Signed-off-by: Antonios Motakis a.mota...@virtualopensystems.com
 Signed-off-by: Nikolay Nikolaev n.nikol...@virtualopensystems.com
 ---
  arch/arm/kvm/mmio.c | 32 
  virt/kvm/arm/vgic.c |  5 -
  2 files changed, 36 insertions(+), 1 deletion(-)

 diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
 index 4cb5a93..1d17831 100644
 --- a/arch/arm/kvm/mmio.c
 +++ b/arch/arm/kvm/mmio.c
 @@ -162,6 +162,35 @@ static int decode_hsr(struct kvm_vcpu *vcpu, 
 phys_addr_t fault_ipa,
   return 0;
  }

 +/**
 + * kvm_handle_mmio - handle an in-kernel MMIO access
 + * @vcpu:pointer to the vcpu performing the access
 + * @run: pointer to the kvm_run structure
 + * @mmio:pointer to the data describing the access
 + *
 + * returns true if the MMIO access has been performed in kernel space,
 + * and false if it needs to be emulated in user space.
 + */
 +static bool handle_kernel_mmio(struct kvm_vcpu *vcpu, struct kvm_run 
 *run,
 + struct kvm_exit_mmio *mmio)
 +{
 + int ret;
 + if (mmio-is_write) {
 + ret = kvm_io_bus_write(vcpu-kvm, KVM_MMIO_BUS, 
 mmio-phys_addr,
 + mmio-len, mmio-data);
 +
 + } else {
 + ret = kvm_io_bus_read(vcpu-kvm, KVM_MMIO_BUS, 
 mmio-phys_addr,
 + mmio-len, mmio-data);
 + }
 + if (!ret) {
 + kvm_prepare_mmio(run, mmio);
 + kvm_handle_mmio_return(vcpu, run);
 + }
 +
 + return !ret;
 +}
 +
  int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
phys_addr_t fault_ipa)
  {
 @@ -200,6 +229,9 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct 
 kvm_run *run,
   if (vgic_handle_mmio(vcpu, run, mmio))
   return 1;

 + if (handle_kernel_mmio(vcpu, run, mmio))
 + return 1;
 +


 We're reconsidering ioeventfds patchseries and we tried to evaluate
 what you suggested here.


 this special-casing of the vgic is now really terrible.  Is there
 anything holding you back from doing the necessary restructure of the
 kvm_bus_io_*() API instead?

 Restructuring the kvm_io_bus_ API is not a big thing (we actually did
 it), but is not directly related to the these patches.
 Of course it can be justified if we do it in the context of removing
 vgic_handle_mmio and leaving only handle_kernel_mmio.


 That would allow us to get rid of the ugly
 Fix it! in the vgic driver as well.

 Going through the vgic_handle_mmio we see that it will require large
 refactoring:
  - there are 15 MMIO ranges for the vgic now - each should be
 registered as a separate device
 Re-correcting Andre's address, sorry:
 Hi Nikolay, Andre,

 what does mandate to register 15 devices? Isn't possible to register a
 single kvm_io_device covering the whole distributor range [base, base +
 KVM_VGIC_V2_DIST_SIZE] (current code) and in associated
 kvm_io_device_ops read/write locate the addressed range and do the same
 as what is done in current vgic_handle_mmio? Isn't it done that way for
 
 Well, then we'll actually get slower mmio processing. Instead of calling
 vgic_handle_mmio in io_mem_abort, we'll be calling kvm_io_bus_write.
 This just adds another level of translation (i.e. find the kvm_io_ device)
 and the underlying vgic code will remain almost the same.

Agreed. That was one possibility I came around also, but I think it
defeats the purpose of the rework, which is mostly to get rid of the
GIC's private MMIO dispatching code, right?

But honestly I would happily sacrifice performance for easier VGIC
code - especially if one thinks about security for instance. Though I
think that another memory reference doesn't really matter in this
context ;-)

 the ioapic? what do I miss?
 I looked quickly in the ioapic code, and if I get it right there are no 
 ranges'
 like what we have with the GIC. They have this regselect/regwindow concept
 and they seem to have much less registers to handle. GIC seems a lot more
 complex in terms of MMIO interface.

Right, that was my impression, too. IOAPIC isn't really comparable to
the GIC in 

Re: [PATCH v2 03/15] arm/arm64: KVM: refactor vgic_handle_mmio() function

2014-10-31 Thread Andre Przywara
Hi Christoffer,

On 15/10/14 17:25, Christoffer Dall wrote:
 On Thu, Aug 21, 2014 at 02:06:44PM +0100, Andre Przywara wrote:
 Currently we only need to deal with one MMIO region for the GIC
 emulation, but we soon need to extend this. Refactor the existing
 code to allow easier addition of different ranges without code
 duplication.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  virt/kvm/arm/vgic.c |   72 
 ---
  1 file changed, 51 insertions(+), 21 deletions(-)

 diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
 index bba8692..3b6f78d 100644
 --- a/virt/kvm/arm/vgic.c
 +++ b/virt/kvm/arm/vgic.c
 @@ -925,37 +925,28 @@ static bool vgic_validate_access(const struct 
 vgic_dist *dist,
  return true;
  }

 -/**
 - * vgic_handle_mmio - handle an in-kernel MMIO access
 +/*
 + * vgic_handle_mmio_range - handle an in-kernel MMIO access
   * @vcpu:   pointer to the vcpu performing the access
   * @run:pointer to the kvm_run structure
   * @mmio:   pointer to the data describing the access
 + * @ranges: pointer to the register defining structure
 + * @mmio_base:  base address for this mapping
   *
 - * returns true if the MMIO access has been performed in kernel space,
 - * and false if it needs to be emulated in user space.
 + * returns true if the MMIO access could be performed
   */
 -bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
 -  struct kvm_exit_mmio *mmio)
 +static bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run 
 *run,
 +struct kvm_exit_mmio *mmio,
 +const struct mmio_range *ranges,
 +unsigned long mmio_base)

 now when we're chopping this up and about to add more logic based on
 our struct mmio_range, I think we should really consider getting rid of
 that comment abou the kvm_bus_io_*() API or actually use that API.

So I did some research in this area. The API is meant to separate
devices on a bus, so we would still need the structure to tell the
single registers apart. The users of kvm_io_bus do this all in one
switch/case, which would mean a step back in our case. Also we need more
members than just base and length.
So though I didn't try it, I guess it wouldn't be a win for us, I am not
even sure it would produce less code.
So I am more looking at removing the comment.


  {
  const struct mmio_range *range;
  struct vgic_dist *dist = vcpu-kvm-arch.vgic;
 -unsigned long base = dist-vgic_dist_base;
  bool updated_state;
  unsigned long offset;

 -if (!irqchip_in_kernel(vcpu-kvm) ||
 -mmio-phys_addr  base ||
 -(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;
 -}
 -
 -offset = mmio-phys_addr - base;
 -range = find_matching_range(vgic_dist_ranges, mmio, offset);
 +offset = mmio-phys_addr - mmio_base;
 +range = find_matching_range(ranges, mmio, offset);
  if (unlikely(!range || !range-handle_mmio)) {
  pr_warn(Unhandled access %d %08llx %d\n,
  mmio-is_write, mmio-phys_addr, mmio-len);
 @@ -963,7 +954,7 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct 
 kvm_run *run,
  }

  spin_lock(vcpu-kvm-arch.vgic.lock);
 -offset = mmio-phys_addr - range-base - base;
 +offset -= range-base;
  if (vgic_validate_access(dist, range, offset)) {
  updated_state = range-handle_mmio(vcpu, mmio, offset);
  } else {
 @@ -981,6 +972,45 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct 
 kvm_run *run,
  return true;
  }

 +#define IS_IN_RANGE(addr, alen, base, len) \
 +(((addr) = (base))  (((addr) + (alen))  ((base) + (len

 that should be = ((base) + (len)) right?

Indeed, thanks for spotting.

 that's a lot of parenthesis, how about creating a static inline instead?

 you could also rename alen to access_len

Will fix this.

Cheers,
Andre.


 +
 +static bool vgic_v2_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
 +struct kvm_exit_mmio *mmio)
 +{
 +unsigned long base = vcpu-kvm-arch.vgic.vgic_dist_base;
 +
 +if (!IS_IN_RANGE(mmio-phys_addr, mmio-len, base,
 + KVM_VGIC_V2_DIST_SIZE))
 +return false;
 +
 +/* GICv2 does not support accesses wider than 32 bits */
 +if (mmio-len  4) {
 +kvm_inject_dabt(vcpu, mmio-phys_addr);
 +return true;
 +}
 +
 +return vgic_handle_mmio_range(vcpu, run, mmio, vgic_dist_ranges, base);
 +}
 +
 +/**
 + * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
 + * @vcpu:  pointer to the vcpu performing the access
 + * @run:   pointer to the kvm_run structure
 + * @mmio:  pointer

Re: [PATCH v2 04/15] arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones

2014-10-31 Thread Andre Przywara
Hi Christoffer,

On 15/10/14 17:26, Christoffer Dall wrote:
 On Thu, Aug 21, 2014 at 02:06:45PM +0100, Andre Przywara wrote:
 Some GICv3 registers can and will be accessed as 64 bit registers.
 Currently the register handling code can only deal with 32 bit
 accesses, so we do two consecutive calls to cover this.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  virt/kvm/arm/vgic.c |   48 +---
  1 file changed, 45 insertions(+), 3 deletions(-)

 diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
 index 3b6f78d..bef9aa0 100644
 --- a/virt/kvm/arm/vgic.c
 +++ b/virt/kvm/arm/vgic.c
 @@ -926,6 +926,48 @@ static bool vgic_validate_access(const struct vgic_dist 
 *dist,
  }
  
  /*
 + * Call the respective handler function for the given range.
 + * We split up any 64 bit accesses into two consecutive 32 bit
 + * handler calls and merge the result afterwards.
 + */
 +static bool call_range_handler(struct kvm_vcpu *vcpu,
 +   struct kvm_exit_mmio *mmio,
 +   unsigned long offset,
 +   const struct mmio_range *range)
 +{
 +u32 *data32 = (void *)mmio-data;
 +struct kvm_exit_mmio mmio32;
 +bool ret;
 +
 +if (likely(mmio-len = 4))
 +return range-handle_mmio(vcpu, mmio, offset);
 +
 +/*
 + * We assume that any access greater than 4 bytes is actually
 
 Is this an assumption or something that will always hold true at this
 point in the code?  If the former, which situations could it not hold
 and what would happen?  If the latter, we should just state that.

I wasn't so sure about this at the time of writing ;-)
So I see how one can read/write 1, 2, 4, 8 bytes and multiples of 4 or 8
bytes with ldm/ldp. For the latter we don't have syndrome support, so I
take it we don't care about this.
So if nobody sees other supported operand sizes when doing MMIO, I will
rephrase the above comment to be more strict.

 
 + * 8 bytes long, caused by a 64-bit access
 + */
 +
 +mmio32.len = 4;
 +mmio32.is_write = mmio-is_write;
 +
 +mmio32.phys_addr = mmio-phys_addr + 4;
 +if (mmio-is_write)
 +*(u32 *)mmio32.data = data32[1];
 +ret = range-handle_mmio(vcpu, mmio32, offset + 4);
 +if (!mmio-is_write)
 +data32[1] = *(u32 *)mmio32.data;
 +
 +mmio32.phys_addr = mmio-phys_addr;
 +if (mmio-is_write)
 +*(u32 *)mmio32.data = data32[0];
 +ret |= range-handle_mmio(vcpu, mmio32, offset);
 +if (!mmio-is_write)
 +data32[0] = *(u32 *)mmio32.data;
 
 won't this break on a BE system?

Mmh, I remember having this discussed with Marc before. But I see that
it looks suspicious. This whole endianess thing is even more confusing
since the GIC is always LE and the guest as well as KVM already do swapping.
So I rewrote the above function to avoid explicit endianess assumptions,
but am still struggling to get it tested successfully on a bi-endian setup.
As I don't want to hold back the newer patches any longer, I will try to
debug this next week, meanwhile not stating bi-endianness is supported
for the new series.

Cheers,
Andre.

 
 +
 +return ret;
 +}
 +
 +/*
   * vgic_handle_mmio_range - handle an in-kernel MMIO access
   * @vcpu:   pointer to the vcpu performing the access
   * @run:pointer to the kvm_run structure
 @@ -956,10 +998,10 @@ static bool vgic_handle_mmio_range(struct kvm_vcpu 
 *vcpu, struct kvm_run *run,
  spin_lock(vcpu-kvm-arch.vgic.lock);
  offset -= range-base;
  if (vgic_validate_access(dist, range, offset)) {
 -updated_state = range-handle_mmio(vcpu, mmio, offset);
 +updated_state = call_range_handler(vcpu, mmio, offset, range);
  } else {
 -vgic_reg_access(mmio, NULL, offset,
 -ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
 +if (!mmio-is_write)
 +memset(mmio-data, 0, mmio-len);
  updated_state = false;
  }
  spin_unlock(vcpu-kvm-arch.vgic.lock);
 -- 
 1.7.9.5

 
 Thanks,
 -Christoffer
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 05/15] arm/arm64: KVM: introduce per-VM ops

2014-10-31 Thread Andre Przywara
Hi Christoffer,

On 15/10/14 17:27, Christoffer Dall wrote:
 On Thu, Aug 21, 2014 at 02:06:46PM +0100, Andre Przywara wrote:
 Currently we only have one virtual GIC model supported, so all guests
 use the same emulation code. With the addition of another model we
 end up with different guests using potentially different vGIC models,
 so we have to split up some functions to be per VM.
 Introduce a vgic_vm_ops struct to hold function pointers for those
 functions that are different and provide the necessary code to
 initialize them.
 This includes functions that depend on the emulated GIC model only
 and functions that depend on the combination of host and guest GIC.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  include/kvm/arm_vgic.h |   18 --
  virt/kvm/arm/vgic-v2.c |   17 +++--
  virt/kvm/arm/vgic-v3.c |   16 +++--
  virt/kvm/arm/vgic.c|   92 
 +++-
  4 files changed, 113 insertions(+), 30 deletions(-)

 diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
 index 4feac9a..7e7c99e 100644
 --- a/include/kvm/arm_vgic.h
 +++ b/include/kvm/arm_vgic.h
 @@ -99,8 +99,6 @@ struct vgic_vmcr {
  };

  struct vgic_ops {
 - struct vgic_lr  (*get_lr)(const struct kvm_vcpu *, int);
 - void(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
   void(*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
   u64 (*get_elrsr)(const struct kvm_vcpu *vcpu);
   u64 (*get_eisr)(const struct kvm_vcpu *vcpu);
 @@ -123,6 +121,17 @@ struct vgic_params {
   unsigned intmaint_irq;
   /* Virtual control interface base address */
   void __iomem*vctrl_base;
 + bool (*init_emul)(struct kvm *kvm, int type);
 +};
 +
 +struct vgic_vm_ops {
 + struct vgic_lr  (*get_lr)(const struct kvm_vcpu *, int);
 + void(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
 + bool(*handle_mmio)(struct kvm_vcpu *, struct kvm_run *,
 +struct kvm_exit_mmio *);
 + bool(*queue_sgi)(struct kvm_vcpu *vcpu, int irq);
 + void(*unqueue_sgi)(struct kvm_vcpu *vcpu, int irq, int source);
 + int (*vgic_init)(struct kvm *kvm, const struct vgic_params 
 *params);
  };

  struct vgic_dist {
 @@ -131,6 +140,9 @@ struct vgic_dist {
   boolin_kernel;
   boolready;

 + /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 + u32 vgic_model;
 +
   int nr_cpus;
   int nr_irqs;

 @@ -168,6 +180,8 @@ struct vgic_dist {

   /* Bitmap indicating which CPU has something pending */
   unsigned long   irq_pending_on_cpu;
 +
 + struct vgic_vm_ops  vm_ops;
  #endif
  };

 diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
 index 01124ef..90947c6 100644
 --- a/virt/kvm/arm/vgic-v2.c
 +++ b/virt/kvm/arm/vgic-v2.c
 @@ -161,8 +161,6 @@ static void vgic_v2_enable(struct kvm_vcpu *vcpu)
  }

  static const struct vgic_ops vgic_v2_ops = {
 - .get_lr = vgic_v2_get_lr,
 - .set_lr = vgic_v2_set_lr,
   .sync_lr_elrsr  = vgic_v2_sync_lr_elrsr,
   .get_elrsr  = vgic_v2_get_elrsr,
   .get_eisr   = vgic_v2_get_eisr,
 @@ -176,6 +174,20 @@ static const struct vgic_ops vgic_v2_ops = {

  static struct vgic_params vgic_v2_params;

 +static bool vgic_v2_init_emul(struct kvm *kvm, int type)
 +{
 + struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
 +
 + switch (type) {
 + case KVM_DEV_TYPE_ARM_VGIC_V2:
 + vm_ops-get_lr = vgic_v2_get_lr;
 + vm_ops-set_lr = vgic_v2_set_lr;
 + return true;
 + }
 +
 + return false;
 +}
 +
  /**
   * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
   * @node:pointer to the DT node
 @@ -214,6 +226,7 @@ int vgic_v2_probe(struct device_node *vgic_node,
   ret = -ENOMEM;
   goto out;
   }
 + vgic-init_emul = vgic_v2_init_emul;

 this feels overly complicated, can't each host-support function just
 export this function and we call it directly from the vgic creation
 code?

 That or just keep the host-specific functions the way they are and
 handle the split within these functions?

 Bah, I'm not sure, this patch is just terrible to review...  Perhaps
 it's because we're doing some combination of introducing infrastructure
 and also changing random bits and naming to be version-specific.

OK, I split up the patch to do one thing at a time. This is now 2 bigger
and 2 smaller patches in the new series, and it looks more
review-friendly, I hope.


   vgic-nr_lr = readl_relaxed(vgic-vctrl_base + GICH_VTR);
   vgic-nr_lr = (vgic-nr_lr  0x3f) + 1;
 diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
 index 1c2c8ee..a38339e 100644
 --- a/virt/kvm/arm/vgic-v3.c
 +++ b/virt/kvm/arm/vgic-v3.c

Re: [PATCH v2 01/15] arm/arm64: KVM: rework MPIDR assignment and add accessors

2014-10-31 Thread Andre Przywara
Hi Christoffer,

On 15/10/14 17:25, Christoffer Dall wrote:
 On Thu, Aug 21, 2014 at 02:06:42PM +0100, Andre Przywara wrote:
 The virtual MPIDR registers (containing topology information) for the
 guest are currently mapped linearily to the vcpu_id. Improve this
 mapping for arm64 by using three levels to not artificially limit the
 number of vCPUs. Also add an accessor to later allow easier access to
 a vCPU with a given MPIDR.
 Use this new accessor in the PSCI emulation.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  arch/arm/include/asm/kvm_emulate.h   |2 +-
  arch/arm/include/asm/kvm_host.h  |2 ++
  arch/arm/kvm/arm.c   |   15 +++
  arch/arm/kvm/psci.c  |   15 ---
  arch/arm64/include/asm/kvm_emulate.h |3 ++-
  arch/arm64/include/asm/kvm_host.h|2 ++
  arch/arm64/kvm/sys_regs.c|   11 +--
  7 files changed, 35 insertions(+), 15 deletions(-)

 diff --git a/arch/arm/include/asm/kvm_emulate.h 
 b/arch/arm/include/asm/kvm_emulate.h
 index 69b7469..18e45f7 100644
 --- a/arch/arm/include/asm/kvm_emulate.h
 +++ b/arch/arm/include/asm/kvm_emulate.h
 @@ -159,7 +159,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu 
 *vcpu)
  
  static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
  {
 -return vcpu-arch.cp15[c0_MPIDR];
 +return vcpu-arch.cp15[c0_MPIDR]  MPIDR_HWID_BITMASK;
 
 why?

Because of the two current users one did that masking afterwards and the
second does not care (applies an ever stricter mask).
All the subsequent users in the GICv3 emulation also do this, so I
deemed it useful to have the masking in here. For KVM purposes I guess
we only are interested in the affinity bits. I can rename the function
to make this more obvious if you like.

Cheers,
Andre.

  }
  
  static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
 diff --git a/arch/arm/include/asm/kvm_host.h 
 b/arch/arm/include/asm/kvm_host.h
 index 6dfb404..cf99ad0 100644
 --- a/arch/arm/include/asm/kvm_host.h
 +++ b/arch/arm/include/asm/kvm_host.h
 @@ -233,4 +233,6 @@ static inline void vgic_arch_setup(const struct 
 vgic_params *vgic)
  int kvm_perf_init(void);
  int kvm_perf_teardown(void);
  
 +struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 +
  #endif /* __ARM_KVM_HOST_H__ */
 diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
 index 7d5065e..addb990 100644
 --- a/arch/arm/kvm/arm.c
 +++ b/arch/arm/kvm/arm.c
 @@ -990,6 +990,21 @@ static void check_kvm_target_cpu(void *ret)
  *(int *)ret = kvm_target_cpu();
  }
  
 +struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
 +{
 +unsigned long c_mpidr;
 +struct kvm_vcpu *vcpu;
 +int i;
 +
 +mpidr = MPIDR_HWID_BITMASK;
 +kvm_for_each_vcpu(i, vcpu, kvm) {
 +c_mpidr = kvm_vcpu_get_mpidr(vcpu);
 +if (c_mpidr == mpidr)
 +return vcpu;
 +}
 +return NULL;
 +}
 +
  /**
   * Initialize Hyp-mode and memory mappings on all CPUs.
   */
 diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
 index 09cf377..49f0992 100644
 --- a/arch/arm/kvm/psci.c
 +++ b/arch/arm/kvm/psci.c
 @@ -21,6 +21,7 @@
  #include asm/cputype.h
  #include asm/kvm_emulate.h
  #include asm/kvm_psci.h
 +#include asm/kvm_host.h
  
  /*
   * This is an implementation of the Power State Coordination Interface
 @@ -65,25 +66,17 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
  static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
  {
  struct kvm *kvm = source_vcpu-kvm;
 -struct kvm_vcpu *vcpu = NULL, *tmp;
 +struct kvm_vcpu *vcpu = NULL;
  wait_queue_head_t *wq;
  unsigned long cpu_id;
  unsigned long context_id;
 -unsigned long mpidr;
  phys_addr_t target_pc;
 -int i;
  
 -cpu_id = *vcpu_reg(source_vcpu, 1);
 +cpu_id = *vcpu_reg(source_vcpu, 1)  MPIDR_HWID_BITMASK;
  if (vcpu_mode_is_32bit(source_vcpu))
  cpu_id = ~((u32) 0);
  
 -kvm_for_each_vcpu(i, tmp, kvm) {
 -mpidr = kvm_vcpu_get_mpidr(tmp);
 -if ((mpidr  MPIDR_HWID_BITMASK) == (cpu_id  
 MPIDR_HWID_BITMASK)) {
 -vcpu = tmp;
 -break;
 -}
 -}
 +vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id);
  
  /*
   * Make sure the caller requested a valid CPU and that the CPU is
 diff --git a/arch/arm64/include/asm/kvm_emulate.h 
 b/arch/arm64/include/asm/kvm_emulate.h
 index fdc3e21..4b8d636 100644
 --- a/arch/arm64/include/asm/kvm_emulate.h
 +++ b/arch/arm64/include/asm/kvm_emulate.h
 @@ -27,6 +27,7 @@
  #include asm/kvm_arm.h
  #include asm/kvm_mmio.h
  #include asm/ptrace.h
 +#include asm/cputype.h
  
  unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, u8 reg_num);
  unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu);
 @@ -179,7 +180,7 @@ static inline u8 kvm_vcpu_trap_get_fault(const struct 
 kvm_vcpu *vcpu)
  
  static inline unsigned long

Re: [PATCH v2 06/15] arm/arm64: KVM: make the maximum number of vCPUs a per-VM value

2014-10-31 Thread Andre Przywara
On 15/10/14 17:27, Christoffer Dall wrote:
 On Thu, Aug 21, 2014 at 02:06:47PM +0100, Andre Przywara wrote:
 Currently the maximum number of vCPUs supported is a global value
 limited by the used GIC model. GICv3 will lift this limit, but we
 still need to observe it for guests using GICv2.
 So the maximum number of vCPUs is per-VM value, depending on the
 GIC model the guest uses.
 Store and check the value in struct kvm_arch, but keep it down to
 8 for now.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  arch/arm/include/asm/kvm_host.h   |1 +
  arch/arm/kvm/arm.c|6 ++
  arch/arm64/include/asm/kvm_host.h |3 +++
  virt/kvm/arm/vgic-v2.c|5 +
  virt/kvm/arm/vgic-v3.c|6 ++
  5 files changed, 21 insertions(+)

 diff --git a/arch/arm/include/asm/kvm_host.h 
 b/arch/arm/include/asm/kvm_host.h
 index cf99ad0..0638419 100644
 --- a/arch/arm/include/asm/kvm_host.h
 +++ b/arch/arm/include/asm/kvm_host.h
 @@ -67,6 +67,7 @@ struct kvm_arch {
  
  /* Interrupt controller */
  struct vgic_distvgic;
 +int max_vcpus;
  };
  
  #define KVM_NR_MEM_OBJS 40
 diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
 index 157e1b6..190f05f 100644
 --- a/arch/arm/kvm/arm.c
 +++ b/arch/arm/kvm/arm.c
 @@ -142,6 +142,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
  
  /* Mark the initial VMID generation invalid */
  kvm-arch.vmid_gen = 0;
 +kvm-arch.max_vcpus = CONFIG_KVM_ARM_MAX_VCPUS;
  
  return ret;
  out_free_stage2_pgd:
 @@ -223,6 +224,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, 
 unsigned int id)
  int err;
  struct kvm_vcpu *vcpu;
  
 +if (id = kvm-arch.max_vcpus) {
 +err = -EINVAL;
 +goto out;
 +}
 +
  vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
  if (!vcpu) {
  err = -ENOMEM;
 diff --git a/arch/arm64/include/asm/kvm_host.h 
 b/arch/arm64/include/asm/kvm_host.h
 index 017fbae..a325161 100644
 --- a/arch/arm64/include/asm/kvm_host.h
 +++ b/arch/arm64/include/asm/kvm_host.h
 @@ -58,6 +58,9 @@ struct kvm_arch {
  /* VTTBR value associated with above pgd and vmid */
  u64vttbr;
  
 +/* The maximum number of vCPUs depends on the used GIC model */
 +int max_vcpus;
 +
  /* Interrupt controller */
  struct vgic_distvgic;
  
 diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
 index 90947c6..c7362ff 100644
 --- a/virt/kvm/arm/vgic-v2.c
 +++ b/virt/kvm/arm/vgic-v2.c
 @@ -177,11 +177,16 @@ static struct vgic_params vgic_v2_params;
  static bool vgic_v2_init_emul(struct kvm *kvm, int type)
  {
  struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
 +int nr_vcpus;
  
  switch (type) {
  case KVM_DEV_TYPE_ARM_VGIC_V2:
 +nr_vcpus = atomic_read(kvm-online_vcpus);
 +if (nr_vcpus  8)
 +return false;
  vm_ops-get_lr = vgic_v2_get_lr;
  vm_ops-set_lr = vgic_v2_set_lr;
 +kvm-arch.max_vcpus = 8;
  return true;
  }
  
 diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
 index a38339e..86e8b99 100644
 --- a/virt/kvm/arm/vgic-v3.c
 +++ b/virt/kvm/arm/vgic-v3.c
 @@ -171,11 +171,17 @@ static const struct vgic_ops vgic_v3_ops = {
  static bool vgic_v3_init_emul_compat(struct kvm *kvm, int type)
  {
  struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
 +int nr_vcpus;
  
  switch (type) {
  case KVM_DEV_TYPE_ARM_VGIC_V2:
 +nr_vcpus = atomic_read(kvm-online_vcpus);
 +if (nr_vcpus  8)
 +return false;
 +
 
 I have a feeling we could be seeing this error a bit, could we dedicate
 an error code for the purpose or print a ratelimited warning or
 something?

Did the latter. To be found in an inbox near you very soon.

Cheers,
Andre.

 
  vm_ops-get_lr = vgic_v3_get_lr;
  vm_ops-set_lr = vgic_v3_set_lr;
 +kvm-arch.max_vcpus = 8;
  return true;
  }
  return false;
 -- 
 1.7.9.5

 Thanks,
 -Christoffer
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 00/15] KVM GICv3 emulation

2014-10-08 Thread Andre Przywara


On 08/10/14 05:08, wanghaibin wrote:
 On 2014/8/21 21:06, Andre Przywara wrote:
 
 
 GICv3 is the ARM generic interrupt controller designed to overcome
 some limits of the prevalent GICv2. Most notably it lifts the 8-CPU
 limit. Though with recent patches from Marc there is support for
 hosts to use a GICv3, the CPU limitation still applies to KVM guests,
 since the current code emulates a GICv2 only.
 Also, GICv2 backward compatibility being optional in GICv3, a number
 of systems won't be able to run GICv2 guests.

 This patch series provides code to emulate a GICv3 distributor and
 redistributor for any KVM guest. It requires a GICv3 in the host to
 work. With those patches one can run guests efficiently on any GICv3
 host. It has the following features:
 - Affinity routing (support for up to 255 VCPUs, more possible)
 
 Hi, Andre, in
   struct vgic_dist {
   
 
   /* Bitmap indicating which CPU has something pending */
   unsigned long   irq_pending_on_cpu;
   }
 the irq_pending_on_cpu parameter type just **unsigned long**.
 
 See the vgic_update_state func:
   void vgic_update_state(struct kvm *kvm)
   {
   ...
 
   kvm_for_each_vcpu(c, vcpu, kvm) {
   if (compute_pending_for_cpu(vcpu)) {
   pr_debug(CPU%d has pending interrupts\n, c);
   set_bit(c, dist-irq_pending_on_cpu);
   }
   }
   }
 
 Maybe when the VCPU id greater than 64, and has pending irq, After 
 calculated,  here:
   set_bit(c, dist-irq_pending_on_cpu);
 must be wrong. Isn't it ?

Indeed, thanks for spotting this. Marc has found this already some weeks
ago and the fix is already in the latest branches[1][2].
Once -rc1 is out I will need to respin my patches anyway.

Cheers,
Andre.

[1]
https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/vgic-dyn
[2]
https://git.kernel.org/cgit/linux/kernel/git/kvmarm/kvmarm.git/log/?h=next

 
 - System registers (as opposed to MMIO access)
 - No ITS
 - No priority support (as the GICv2 emulation)
 - No save / restore support so far (will be added soon)

 The first 11 patches actually refactor the current VGIC code to make
 room for a different VGIC model to be dropped in with Patch 12/15.
 The remaining patches connect the new model to the kernel backend and
 the userland facing code.

 The series goes on top of v3.17-rc1 and Marc's vgic-dyn series[2].
 The necessary patches for kvmtool to enable the guest's GICv3 have
 been posted here before [3], an updated version will follow as soon
 as the kvmtools tree has been updated.

 There was some testing on the fast model with some I/O and interrupt
 affinity shuffling in a Linux guest with a varying number of VCPUs as
 well as some testing on a Juno board (GICv2 only, to spot
 regressions).

 Please review and test.
 I would be grateful for people to test for GICv2 regressions also
 (so on a GICv2 host with current kvmtool/qemu), as there is quite
 some refactoring on that front.

 Much of the code was inspired by MarcZ, also kudos to him for doing
 the rather painful rebase on top of v3.17-rc1.

 Cheers,
 Andre.

 [1] https://lists.cs.columbia.edu/pipermail/kvmarm/2014-June/010060.html
 [2] 
 https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/vgic-dyn
 [3] https://lists.cs.columbia.edu/pipermail/kvmarm/2014-June/010086.html

 Changes v1 ... v2:
 * rebase to v3.17-rc1, caused quite some changes to the init code
 * new 9/15 patch to make 10/15 smaller
 * fix wrongly ordered cp15 register trap entry (MarcZ)
 * fix SGI broadcast (thanks to wanghaibin for spotting)
 * fix broken bailout path in kvm_vgic_create (wanghaibin)
 * check return value of init_emulation_ops() (wanghaibin)
 * fix return value check in vgic_[sg]et_attr()
 * add header inclusion guards
 * remove double definition of VCPU_NOT_ALLOCATED
 * some code move-around
 * whitespace fixes


 Andre Przywara (15):
   arm/arm64: KVM: rework MPIDR assignment and add accessors
   arm/arm64: KVM: pass down user space provided GIC type into vGIC code
   arm/arm64: KVM: refactor vgic_handle_mmio() function
   arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones
   arm/arm64: KVM: introduce per-VM ops
   arm/arm64: KVM: make the maximum number of vCPUs a per-VM value
   arm/arm64: KVM: make the value of ICC_SRE_EL1 a per-VM variable
   arm/arm64: KVM: refactor MMIO accessors
   arm/arm64: KVM: refactor/wrap vgic_set/get_attr()
   arm/arm64: KVM: split GICv2 specific emulation code from vgic.c
   arm/arm64: KVM: add opaque private pointer to MMIO accessors
   arm/arm64: KVM: add virtual GICv3 distributor emulation
   arm/arm64: KVM: add SGI system register trapping
   arm/arm64: KVM: enable kernel side of GICv3 emulation
   arm/arm64: KVM: allow userland to request a virtual GICv3

  arch/arm

Re: [PATCH v5 0/4] kvmtool: ARM/ARM64: Misc updates

2014-10-01 Thread Andre Przywara
Hi Anup,

On 01/10/14 11:34, Anup Patel wrote:
 This patchset updates KVMTOOL to use some of the features
 supported by Linux-3.16 KVM ARM/ARM64, such as:
 
 1. Target CPU == Host using KVM_ARM_PREFERRED_TARGET vm ioctl
 2. Target CPU type Potenza for using KVMTOOL on X-Gene
 3. PSCI v0.2 support for Aarch32 and Aarch64 guest
 4. System event exit reason

Thanks for the quick respin. Looks fine now for me.


For the whole v5 series:

Reviewed-by: Andre Przywara andre.przyw...@arm.com

Cheers,
Andre.

 Changes since v4:
 - Avoid using magic '0' target for kvm arm generic target
 - Added comment for why we need Potenza target in KVMTOOL
 
 Changes since v3:
 - Add generic targets for aarch32 and aarch64 which are used
   by KVMTOOL when target type returned by KVM_ARM_PREFERRED_TARGET
   vm ioctl is not known to KVMTOOL
 - Print more info when handling system reset event
 
 Changes since v2:
 - Use target type returned by KVM_ARM_PREFERRED_TARGET vm ioctl
   for VCPU init such that we don't need to update KVMTOOL for
   every new host hardware
 - Simplify DTB generation for PSCI node
 
 Changes since v1:
 - Drop the patch to fix compile error for aarch64
 - Fallback to old method of trying all target types if
 KVM_ARM_PREFERRED_TARGET vm ioctl fails
 - Print more info when handling KVM_EXIT_SYSTEM_EVENT
 
 Anup Patel (4):
   kvmtool: ARM: Use KVM_ARM_PREFERRED_TARGET vm ioctl to determine
 target cpu
   kvmtool: ARM64: Add target type potenza for aarch64
   kvmtool: Handle exit reason KVM_EXIT_SYSTEM_EVENT
   kvmtool: ARM/ARM64: Provide PSCI-0.2 to guest when KVM supports it
 
  tools/kvm/arm/aarch32/arm-cpu.c |8 +++
  tools/kvm/arm/aarch64/arm-cpu.c |   23 -
  tools/kvm/arm/fdt.c |   51 +--
  tools/kvm/arm/include/arm-common/kvm-cpu-arch.h |2 +
  tools/kvm/arm/kvm-cpu.c |   61 
 +++
  tools/kvm/kvm-cpu.c |   21 
  6 files changed, 149 insertions(+), 17 deletions(-)
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] arm/arm64: KVM: Fix BE accesses to GICv2 EISR and ELRSR regs

2014-10-01 Thread Andre Przywara
Hi Christoffer,

On 28/09/14 15:04, Christoffer Dall wrote:
 The EIRSR and ELRSR registers are 32-bit registers on GICv2, and we
 store these as an array of two such registers on the vgic vcpu struct.
 However, we access them as a single 64-bit value or as a bitmap pointer
 in the generic vgic code, which breaks BE support.
 
 Instead, store them as u64 values on the vgic structure and do the
 word-swapping in the assembly code, which already handles the byte order
 for BE systems.

I am wondering if that approach isn't too involved.
EISR and ELRSR are 32-bit registers, and AFAIK the GIC is always LE on
the hardware side. So by claiming we have a 64bit register we introduce
too much hassle, right?
Wouldn't it be better to just fix the registers shortly before we
actually use them?
With my limited endianess experience: Wouldn't this patch solve the EISR
part (copy  pasted, so for eyes only ;-)

@@ -92,13 +89,10 @@ static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu)
 {
u64 val;

-#if BITS_PER_LONG == 64
-   val  = vcpu-arch.vgic_cpu.vgic_v2.vgic_eisr[1];
+   val  = le32_to_cpu(vcpu-arch.vgic_cpu.vgic_v2.vgic_eisr[1]);
val = 32;
-   val |= vcpu-arch.vgic_cpu.vgic_v2.vgic_eisr[0];
-#else
-   val = *(u64 *)vcpu-arch.vgic_cpu.vgic_v2.vgic_eisr;
-#endif
+   val |= le32_to_cpu(vcpu-arch.vgic_cpu.vgic_v2.vgic_eisr[0]);
+
return val;
 }

(BTW: Wasn't that 64 bit optimization path the wrong way round here?)

Please bear with me if this is complete nonsense, could well twisted my
mind once too much ;-)

Still thinking about a clever solution for that strange sync_elrsr()
thing ...

Cheers,
Andre.

 
 Signed-off-by: Christoffer Dall christoffer.d...@linaro.org
 ---
 I don't have a working BE configuration, so sending this out as an
 *UNTESTED on BE* RFC in hoping that someone with a working setup can
 give it a test for me (Will tells me Virtio is broken with kvmtool no BE
 hosts though), and to avoid someone else also doing this work.
 
  arch/arm/kvm/interrupts_head.S  |  7 +++
  arch/arm64/kvm/vgic-v2-switch.S | 12 
  include/kvm/arm_vgic.h  |  4 ++--
  virt/kvm/arm/vgic-v2.c  | 24 +++-
  virt/kvm/arm/vgic.c | 18 --
  5 files changed, 36 insertions(+), 29 deletions(-)
 
 diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
 index 98c8c5b..14d4883 100644
 --- a/arch/arm/kvm/interrupts_head.S
 +++ b/arch/arm/kvm/interrupts_head.S
 @@ -433,10 +433,17 @@ ARM_BE8(rev r10, r10)
   str r3, [r11, #VGIC_V2_CPU_HCR]
   str r4, [r11, #VGIC_V2_CPU_VMCR]
   str r5, [r11, #VGIC_V2_CPU_MISR]
 +#ifdef CONFIG_CPU_ENDIAN_BE8
 + str r6, [r11, #(VGIC_V2_CPU_EISR + 4)]
 + str r7, [r11, #VGIC_V2_CPU_EISR]
 + str r8, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
 + str r9, [r11, #VGIC_V2_CPU_ELRSR]
 +#else
   str r6, [r11, #VGIC_V2_CPU_EISR]
   str r7, [r11, #(VGIC_V2_CPU_EISR + 4)]
   str r8, [r11, #VGIC_V2_CPU_ELRSR]
   str r9, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
 +#endif
   str r10, [r11, #VGIC_V2_CPU_APR]
  
   /* Clear GICH_HCR */
 diff --git a/arch/arm64/kvm/vgic-v2-switch.S b/arch/arm64/kvm/vgic-v2-switch.S
 index ae21177..f002fe1 100644
 --- a/arch/arm64/kvm/vgic-v2-switch.S
 +++ b/arch/arm64/kvm/vgic-v2-switch.S
 @@ -67,10 +67,14 @@ CPU_BE(   rev w11, w11 )
   str w4, [x3, #VGIC_V2_CPU_HCR]
   str w5, [x3, #VGIC_V2_CPU_VMCR]
   str w6, [x3, #VGIC_V2_CPU_MISR]
 - str w7, [x3, #VGIC_V2_CPU_EISR]
 - str w8, [x3, #(VGIC_V2_CPU_EISR + 4)]
 - str w9, [x3, #VGIC_V2_CPU_ELRSR]
 - str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)]
 +CPU_LE(  str w7, [x3, #VGIC_V2_CPU_EISR] )
 +CPU_LE(  str w8, [x3, #(VGIC_V2_CPU_EISR + 4)] )
 +CPU_LE(  str w9, [x3, #VGIC_V2_CPU_ELRSR] )
 +CPU_LE(  str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)] )
 +CPU_BE(  str w7, [x3, #(VGIC_V2_CPU_EISR + 4)] )
 +CPU_BE(  str w8, [x3, #VGIC_V2_CPU_EISR] )
 +CPU_BE(  str w9, [x3, #(VGIC_V2_CPU_ELRSR + 4)] )
 +CPU_BE(  str w10, [x3, #VGIC_V2_CPU_ELRSR] )
   str w11, [x3, #VGIC_V2_CPU_APR]
  
   /* Clear GICH_HCR */
 diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
 index 35b0c12..c66dc9ed 100644
 --- a/include/kvm/arm_vgic.h
 +++ b/include/kvm/arm_vgic.h
 @@ -168,8 +168,8 @@ struct vgic_v2_cpu_if {
   u32 vgic_hcr;
   u32 vgic_vmcr;
   u32 vgic_misr;  /* Saved only */
 - u32 vgic_eisr[2];   /* Saved only */
 - u32 vgic_elrsr[2];  /* Saved only */
 + u64 vgic_eisr;  /* Saved only */
 + u64 vgic_elrsr; /* Saved only */
   u32 vgic_apr;
   u32 vgic_lr[VGIC_V2_MAX_LRS];
  };
 diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
 index 

Re: [PATCH v4 1/4] kvmtool: ARM: Use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target cpu

2014-09-30 Thread Andre Przywara
Hi Anup,

thanks for the re-spin and sorry for the delay.

Looks better now, some minor comments below.

On 19/09/14 00:57, Anup Patel wrote:
 Instead, of trying out each and every target type we should
 use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target type
 for KVM ARM/ARM64.
 
 If KVM_ARM_PREFERRED_TARGET vm ioctl fails then we fallback to
 old method of trying all known target types.
 
 If KVM_ARM_PREFERRED_TARGET vm ioctl succeeds but the returned
 target type is not known to KVMTOOL then we forcefully init
 VCPU with target type returned by KVM_ARM_PREFERRED_TARGET vm ioctl.
 
 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/aarch32/arm-cpu.c |9 ++-
  tools/kvm/arm/aarch64/arm-cpu.c |   10 ++--
  tools/kvm/arm/kvm-cpu.c |   52 
 ++-
  3 files changed, 57 insertions(+), 14 deletions(-)
 
 diff --git a/tools/kvm/arm/aarch32/arm-cpu.c b/tools/kvm/arm/aarch32/arm-cpu.c
 index 71b98fe..0d2ff11 100644
 --- a/tools/kvm/arm/aarch32/arm-cpu.c
 +++ b/tools/kvm/arm/aarch32/arm-cpu.c
 @@ -22,6 +22,12 @@ static int arm_cpu__vcpu_init(struct kvm_cpu *vcpu)
   return 0;
  }
  
 +static struct kvm_arm_target target_generic_v7 = {
 + .id = UINT_MAX,
 + .compatible = arm,arm-v7,
 + .init   = arm_cpu__vcpu_init,
 +};
 +
  static struct kvm_arm_target target_cortex_a15 = {
   .id = KVM_ARM_TARGET_CORTEX_A15,
   .compatible = arm,cortex-a15,
 @@ -36,7 +42,8 @@ static struct kvm_arm_target target_cortex_a7 = {
  
  static int arm_cpu__core_init(struct kvm *kvm)
  {
 - return (kvm_cpu__register_kvm_arm_target(target_cortex_a15) ||
 + return (kvm_cpu__register_kvm_arm_target(target_generic_v7) ||
 + kvm_cpu__register_kvm_arm_target(target_cortex_a15) ||
   kvm_cpu__register_kvm_arm_target(target_cortex_a7));
  }

I wonder if you could avoid the registration of this target and instead
reference it later directly (instead of using a magic 0 index)?
This way you wouldn't need to care about avoiding accidental .id matches
with the UINT_MAX above.

  core_init(arm_cpu__core_init);
 diff --git a/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c
 index ce5ea2f..9ee3da3 100644
 --- a/tools/kvm/arm/aarch64/arm-cpu.c
 +++ b/tools/kvm/arm/aarch64/arm-cpu.c
 @@ -16,13 +16,18 @@ static void generate_fdt_nodes(void *fdt, struct kvm 
 *kvm, u32 gic_phandle)
   timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
  }
  
 -
  static int arm_cpu__vcpu_init(struct kvm_cpu *vcpu)
  {
   vcpu-generate_fdt_nodes = generate_fdt_nodes;
   return 0;
  }
  
 +static struct kvm_arm_target target_generic_v8 = {
 + .id = UINT_MAX,
 + .compatible = arm,arm-v8,
 + .init   = arm_cpu__vcpu_init,
 +};
 +
  static struct kvm_arm_target target_aem_v8 = {
   .id = KVM_ARM_TARGET_AEM_V8,
   .compatible = arm,arm-v8,
 @@ -43,7 +48,8 @@ static struct kvm_arm_target target_cortex_a57 = {
  
  static int arm_cpu__core_init(struct kvm *kvm)
  {
 - return (kvm_cpu__register_kvm_arm_target(target_aem_v8) ||
 + return (kvm_cpu__register_kvm_arm_target(target_generic_v8) ||
 + kvm_cpu__register_kvm_arm_target(target_aem_v8) ||
   kvm_cpu__register_kvm_arm_target(target_foundation_v8) ||
   kvm_cpu__register_kvm_arm_target(target_cortex_a57));
  }

(same thing like for v7 here)

 diff --git a/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c
 index aeaa4cf..6de5344 100644
 --- a/tools/kvm/arm/kvm-cpu.c
 +++ b/tools/kvm/arm/kvm-cpu.c
 @@ -13,7 +13,7 @@ int kvm_cpu__get_debug_fd(void)
   return debug_fd;
  }
  
 -static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS];
 +static struct kvm_arm_target *kvm_arm_targets[KVM_ARM_NUM_TARGETS+1];

w/s issue

  int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
  {
   unsigned int i = 0;
 @@ -33,7 +33,8 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   struct kvm_arm_target *target;
   struct kvm_cpu *vcpu;
   int coalesced_offset, mmap_size, err = -1;
 - unsigned int i;
 + unsigned int i, target_type;
 + struct kvm_vcpu_init preferred_init;
   struct kvm_vcpu_init vcpu_init = {
   .features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
   };
 @@ -55,19 +56,47 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   if (vcpu-kvm_run == MAP_FAILED)
   die(unable to mmap vcpu fd);
  
 - /* Find an appropriate target CPU type. */
 - for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 - if (!kvm_arm_targets[i])
 - continue;
 - target = kvm_arm_targets[i];
 - vcpu_init.target = target-id;
 + /*
 +  * If preferred target ioctl successful then use 

Re: [PATCH v4 4/4] kvmtool: ARM/ARM64: Provide PSCI-0.2 to guest when KVM supports it

2014-09-30 Thread Andre Przywara
Hi Anup,

this looks good now, only one minor formatting thing below.

On 19/09/14 00:57, Anup Patel wrote:
 If in-kernel KVM support PSCI-0.2 emulation then we should set
 KVM_ARM_VCPU_PSCI_0_2 feature for each guest VCPU and also
 provide arm,psci-0.2,arm,psci as PSCI compatible string.
 
 This patch updates kvm_cpu__arch_init() and setup_fdt() as
 per above.
 
 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/fdt.c |   52 
 ++-
  tools/kvm/arm/kvm-cpu.c |5 +
  2 files changed, 52 insertions(+), 5 deletions(-)
 
 diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c
 index 186a718..a15450e 100644
 --- a/tools/kvm/arm/fdt.c
 +++ b/tools/kvm/arm/fdt.c
 @@ -13,6 +13,7 @@
  #include linux/byteorder.h
  #include linux/kernel.h
  #include linux/sizes.h
 +#include linux/psci.h
  
  static char kern_cmdline[COMMAND_LINE_SIZE];
  
 @@ -84,6 +85,34 @@ static void generate_irq_prop(void *fdt, u8 irq)
   _FDT(fdt_property(fdt, interrupts, irq_prop, sizeof(irq_prop)));
  }
  
 +struct psci_fns {
 + u32 cpu_suspend;
 + u32 cpu_off;
 + u32 cpu_on;
 + u32 migrate;
 +};
 +
 +static struct psci_fns psci_0_1_fns = {
 + .cpu_suspend = KVM_PSCI_FN_CPU_SUSPEND,
 + .cpu_off = KVM_PSCI_FN_CPU_OFF,
 + .cpu_on = KVM_PSCI_FN_CPU_ON,
 + .migrate = KVM_PSCI_FN_MIGRATE,
 +};
 +
 +static struct psci_fns psci_0_2_aarch32_fns = {
 + .cpu_suspend = PSCI_0_2_FN_CPU_SUSPEND,
 + .cpu_off = PSCI_0_2_FN_CPU_OFF,
 + .cpu_on = PSCI_0_2_FN_CPU_ON,
 + .migrate = PSCI_0_2_FN_MIGRATE,
 +};
 +
 +static struct psci_fns psci_0_2_aarch64_fns = {
 + .cpu_suspend = PSCI_0_2_FN64_CPU_SUSPEND,
 + .cpu_off = PSCI_0_2_FN_CPU_OFF,
 + .cpu_on = PSCI_0_2_FN64_CPU_ON,
 + .migrate = PSCI_0_2_FN64_MIGRATE,
 +};
 +
  static int setup_fdt(struct kvm *kvm)
  {
   struct device_header *dev_hdr;
 @@ -93,6 +122,7 @@ static int setup_fdt(struct kvm *kvm)
   cpu_to_fdt64(kvm-arch.memory_guest_start),
   cpu_to_fdt64(kvm-ram_size),
   };
 + struct psci_fns *fns;
   void *fdt   = staging_fdt;
   void *fdt_dest  = guest_flat_to_host(kvm,
kvm-arch.dtb_guest_start);
 @@ -162,12 +192,24 @@ static int setup_fdt(struct kvm *kvm)
  
   /* PSCI firmware */
   _FDT(fdt_begin_node(fdt, psci));
 - _FDT(fdt_property_string(fdt, compatible, arm,psci));
 + if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
 + const char compatible[] = arm,psci-0.2\0arm,psci;
 + _FDT(fdt_property(fdt, compatible,
 +   compatible, sizeof(compatible)));
 + if (kvm-cfg.arch.aarch32_guest) {
 + fns = psci_0_2_aarch32_fns;
 + } else {
 + fns = psci_0_2_aarch64_fns;
 + }

You can remove the braces here.

Given that you fix that:

Reviewed-by: Andre Przywara andre.przyw...@arm.com

Thanks!
Andre

 + } else {
 + _FDT(fdt_property_string(fdt, compatible, arm,psci));
 + fns = psci_0_1_fns;
 + }
   _FDT(fdt_property_string(fdt, method, hvc));
 - _FDT(fdt_property_cell(fdt, cpu_suspend, KVM_PSCI_FN_CPU_SUSPEND));
 - _FDT(fdt_property_cell(fdt, cpu_off, KVM_PSCI_FN_CPU_OFF));
 - _FDT(fdt_property_cell(fdt, cpu_on, KVM_PSCI_FN_CPU_ON));
 - _FDT(fdt_property_cell(fdt, migrate, KVM_PSCI_FN_MIGRATE));
 + _FDT(fdt_property_cell(fdt, cpu_suspend, fns-cpu_suspend));
 + _FDT(fdt_property_cell(fdt, cpu_off, fns-cpu_off));
 + _FDT(fdt_property_cell(fdt, cpu_on, fns-cpu_on));
 + _FDT(fdt_property_cell(fdt, migrate, fns-migrate));
   _FDT(fdt_end_node(fdt));
  
   /* Finalise. */
 diff --git a/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c
 index 6de5344..219de16 100644
 --- a/tools/kvm/arm/kvm-cpu.c
 +++ b/tools/kvm/arm/kvm-cpu.c
 @@ -56,6 +56,11 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   if (vcpu-kvm_run == MAP_FAILED)
   die(unable to mmap vcpu fd);
  
 + /* Set KVM_ARM_VCPU_PSCI_0_2 if available */
 + if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
 + vcpu_init.features[0] |= (1UL  KVM_ARM_VCPU_PSCI_0_2);
 + }
 +
   /*
* If preferred target ioctl successful then use preferred target
* else try each and every target type.
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 3/4] kvmtool: Handle exit reason KVM_EXIT_SYSTEM_EVENT

2014-09-30 Thread Andre Przywara
On 19/09/14 00:57, Anup Patel wrote:
 The KVM_EXIT_SYSTEM_EVENT exit reason was added to define
 architecture independent system-wide events for a Guest.
 
 Currently, it is used by in-kernel PSCI-0.2 emulation of
 KVM ARM/ARM64 to inform user space about PSCI SYSTEM_OFF
 or PSCI SYSTEM_RESET request.
 
 For now, we simply treat all system-wide guest events as
 shutdown request in KVMTOOL.
 
 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/kvm-cpu.c |   21 +
  1 file changed, 21 insertions(+)
 
 diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
 index ee0a8ec..5180039 100644
 --- a/tools/kvm/kvm-cpu.c
 +++ b/tools/kvm/kvm-cpu.c
 @@ -160,6 +160,27 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
   goto exit_kvm;
   case KVM_EXIT_SHUTDOWN:
   goto exit_kvm;
 + case KVM_EXIT_SYSTEM_EVENT:
 + /*
 +  * Print the type of system event and
 +  * treat all system events as shutdown request.
 +  */
 + switch (cpu-kvm_run-system_event.type) {
 + case KVM_SYSTEM_EVENT_SHUTDOWN:
 + printf(  # Info: shutdown system event\n);
 + goto exit_kvm;
 + case KVM_SYSTEM_EVENT_RESET:
 + printf(  # Info: reset system event\n);
 + printf(  # Info: KVMTOOL does not support VM 
 reset\n);
 + printf(  # Info: please re-launch the VM 
 manually\n);
 + goto exit_kvm;
 + default:
 + printf(  # Warning: unknown system event 
 type=%d\n,
 +cpu-kvm_run-system_event.type);
 + printf(  # Info: exiting KVMTOOL\n);
 + goto exit_kvm;
 + };
 + break;
   default: {
   bool ret;
  
 

Looks good to me.

Reviewed-by: Andre Przywara andre.przyw...@arm.com

Cheers,
Andre.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 2/4] kvmtool: ARM64: Add target type potenza for aarch64

2014-09-29 Thread Andre Przywara

On 19/09/14 00:57, Anup Patel wrote:
 The VCPU target type KVM_ARM_TARGET_XGENE_POTENZA is available
 in latest Linux-3.16-rcX or higher hence register aarch64 target
 type for it.

 This patch enables us to run KVMTOOL on X-Gene Potenza host.

I still don't like the addition of another CPU, but for the sake of
running older kernels (which seems to have a use-case in your case) I am
OK with this.
Maybe it's worth adding a comment which states that this list is
closed and just provided to support older kernels?
So that other SoCs don't get funny ideas... ;-)

Cheers,
Andre.


 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/aarch64/arm-cpu.c |9 -
  1 file changed, 8 insertions(+), 1 deletion(-)

 diff --git a/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c
 index 9ee3da3..51a1e2f 100644
 --- a/tools/kvm/arm/aarch64/arm-cpu.c
 +++ b/tools/kvm/arm/aarch64/arm-cpu.c
 @@ -46,11 +46,18 @@ static struct kvm_arm_target target_cortex_a57 = {
   .init   = arm_cpu__vcpu_init,
  };

 +static struct kvm_arm_target target_potenza = {
 + .id = KVM_ARM_TARGET_XGENE_POTENZA,
 + .compatible = arm,arm-v8,
 + .init   = arm_cpu__vcpu_init,
 +};
 +
  static int arm_cpu__core_init(struct kvm *kvm)
  {
   return (kvm_cpu__register_kvm_arm_target(target_generic_v8) ||
   kvm_cpu__register_kvm_arm_target(target_aem_v8) ||
   kvm_cpu__register_kvm_arm_target(target_foundation_v8) ||
 - kvm_cpu__register_kvm_arm_target(target_cortex_a57));
 + kvm_cpu__register_kvm_arm_target(target_cortex_a57) ||
 + kvm_cpu__register_kvm_arm_target(target_potenza));
  }
  core_init(arm_cpu__core_init);


-- IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered 
in England  Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, 
Registered in England  Wales, Company No:  2548782

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] kvmtool/arm{,64}: fix ARM initrd functionality

2014-09-16 Thread Andre Przywara
lkvm -i is currently broken on ARM/ARM64.
We should not try to convert smaller-than-4GB addresses into 64-bit
big endian and then stuff them into u32 variables if we expect to read
anything other than 0 out of it.
Adjust the type to u64 to write the proper address in BE format into
the /chosen node (and also match the address size we formely posted)
and let Linux thus read the right values.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/arm/fdt.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c
index 186a718..1a76b07c 100644
--- a/tools/kvm/arm/fdt.c
+++ b/tools/kvm/arm/fdt.c
@@ -119,8 +119,8 @@ static int setup_fdt(struct kvm *kvm)
 
/* Initrd */
if (kvm-arch.initrd_size != 0) {
-   u32 ird_st_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start);
-   u32 ird_end_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start +
+   u64 ird_st_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start);
+   u64 ird_end_prop = cpu_to_fdt64(kvm-arch.initrd_guest_start +
   kvm-arch.initrd_size);
 
_FDT(fdt_property(fdt, linux,initrd-start,
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/4] kvmtool: ARM: Use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target cpu

2014-09-11 Thread Andre Przywara
Hi Anup,

On 08/09/14 09:17, Anup Patel wrote:
 Instead, of trying out each and every target type we should
 use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target type
 for KVM ARM/ARM64.
 
 If KVM_ARM_PREFERRED_TARGET vm ioctl fails then we fallback to
 old method of trying all known target types.
 
 If KVM_ARM_PREFERRED_TARGET vm ioctl succeeds but the returned
 target type is not known to KVMTOOL then we forcefully init
 VCPU with target type returned by KVM_ARM_PREFERRED_TARGET vm ioctl.
 
 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/kvm-cpu.c |   52 
 +--
  1 file changed, 41 insertions(+), 11 deletions(-)
 
 diff --git a/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c
 index aeaa4cf..ba7a762 100644
 --- a/tools/kvm/arm/kvm-cpu.c
 +++ b/tools/kvm/arm/kvm-cpu.c
 @@ -33,7 +33,8 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   struct kvm_arm_target *target;
   struct kvm_cpu *vcpu;
   int coalesced_offset, mmap_size, err = -1;
 - unsigned int i;
 + unsigned int i, target_type;
 + struct kvm_vcpu_init preferred_init;
   struct kvm_vcpu_init vcpu_init = {
   .features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
   };
 @@ -55,19 +56,47 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   if (vcpu-kvm_run == MAP_FAILED)
   die(unable to mmap vcpu fd);
  
 - /* Find an appropriate target CPU type. */
 - for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 - if (!kvm_arm_targets[i])
 - continue;
 - target = kvm_arm_targets[i];
 - vcpu_init.target = target-id;
 - err = ioctl(vcpu-vcpu_fd, KVM_ARM_VCPU_INIT, vcpu_init);
 - if (!err)
 - break;
 + /*
 +  * If preferred target ioctl successful then use preferred target
 +  * else try each and every target type.
 +  */
 + err = ioctl(kvm-vm_fd, KVM_ARM_PREFERRED_TARGET, preferred_init);
 + if (!err) {
 + /* Match preferred target CPU type. */
 + target = NULL;
 + for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 + if (!kvm_arm_targets[i])
 + continue;
 + if (kvm_arm_targets[i]-id == preferred_init.target) {
 + target = kvm_arm_targets[i];
 + target_type = kvm_arm_targets[i]-id;
 + break;
 + }
 + }
 + if (!target) {
 + target = kvm_arm_targets[0];

I think you missed the part of the patch which adds the now magic zero
member of kvm_arm_targets[]. A simple static initializer should work.

 + target_type = preferred_init.target;

Can't you move that out of the loop, in front of it actually? Then you
can get rid of the line above setting the target_type also, since you
always use the same value now, regardless whether you found that CPU in
the list or not.

 + }
 + } else {
 + /* Find an appropriate target CPU type. */
 + for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 + if (!kvm_arm_targets[i])
 + continue;
 + target = kvm_arm_targets[i];
 + target_type = target-id;
 + vcpu_init.target = target_type;
 + err = ioctl(vcpu-vcpu_fd, KVM_ARM_VCPU_INIT, 
 vcpu_init);
 + if (!err)
 + break;
 + }
 + if (err)
 + die(Unable to find matching target);
   }
  
 + vcpu_init.target = target_type;
 + err = ioctl(vcpu-vcpu_fd, KVM_ARM_VCPU_INIT, vcpu_init);

You should do this only in the if-branch above, since you (try to) call
KVM_ARM_VCPU_INIT already in the else branch before. Otherwise in the
latter case you would do it twice.

Regards,
Andre.

   if (err || target-init(vcpu))
 - die(Unable to initialise ARM vcpu);
 + die(Unable to initialise vcpu);
  
   coalesced_offset = ioctl(kvm-sys_fd, KVM_CHECK_EXTENSION,
KVM_CAP_COALESCED_MMIO);
 @@ -81,6 +110,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   vcpu-cpu_type  = target-id;
   vcpu-cpu_compatible= target-compatible;
   vcpu-is_running= true;
 +
   return vcpu;
  }
  
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/4] kvmtool: ARM64: Add target type potenza for aarch64

2014-09-11 Thread Andre Przywara
Anup,

On 08/09/14 09:17, Anup Patel wrote:
 The VCPU target type KVM_ARM_TARGET_XGENE_POTENZA is available
 in latest Linux-3.16-rcX or higher hence register aarch64 target
 type for it.

 This patch enables us to run KVMTOOL on X-Gene Potenza host.

Why do you need this still if the previous patch got rid of the need for
naming each and every CPU in kvmtool?
Do you care about kernels older than 3.12? I wouldn't bother so much
since you'd need a much newer kvmtool anyway.

Can you consider dropping this patch then?
I'd rather avoid adding CPUs to this list needlessly from now on.

Regards,
Andre.

 
 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/aarch64/arm-cpu.c |9 -
  1 file changed, 8 insertions(+), 1 deletion(-)
 
 diff --git a/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c
 index ce5ea2f..ce526e3 100644
 --- a/tools/kvm/arm/aarch64/arm-cpu.c
 +++ b/tools/kvm/arm/aarch64/arm-cpu.c
 @@ -41,10 +41,17 @@ static struct kvm_arm_target target_cortex_a57 = {
   .init   = arm_cpu__vcpu_init,
  };
  
 +static struct kvm_arm_target target_potenza = {
 + .id = KVM_ARM_TARGET_XGENE_POTENZA,
 + .compatible = arm,arm-v8,
 + .init   = arm_cpu__vcpu_init,
 +};
 +
  static int arm_cpu__core_init(struct kvm *kvm)
  {
   return (kvm_cpu__register_kvm_arm_target(target_aem_v8) ||
   kvm_cpu__register_kvm_arm_target(target_foundation_v8) ||
 - kvm_cpu__register_kvm_arm_target(target_cortex_a57));
 + kvm_cpu__register_kvm_arm_target(target_cortex_a57) ||
 + kvm_cpu__register_kvm_arm_target(target_potenza));
  }
  core_init(arm_cpu__core_init);
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 3/4] kvmtool: Handle exit reason KVM_EXIT_SYSTEM_EVENT

2014-09-11 Thread Andre Przywara

On 08/09/14 09:17, Anup Patel wrote:
 The KVM_EXIT_SYSTEM_EVENT exit reason was added to define
 architecture independent system-wide events for a Guest.
 
 Currently, it is used by in-kernel PSCI-0.2 emulation of
 KVM ARM/ARM64 to inform user space about PSCI SYSTEM_OFF
 or PSCI SYSTEM_RESET request.
 
 For now, we simply treat all system-wide guest events as
 shutdown request in KVMTOOL.

Is that really a good idea to default to exit_kvm?
I find a shutdown a rather drastic default.
Also I'd like to see RESET not easily mapped to shutdown. If the user
resets the box explicitly, it's probably expected to come up again (to
load an updated kernel or proceed with an install).
So what about a more explicit message like: ... please restart the VM
until we gain proper reboot support in kvmtool?

Regards,
Andre.

 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/kvm-cpu.c |   19 +++
  1 file changed, 19 insertions(+)
 
 diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
 index ee0a8ec..6d01192 100644
 --- a/tools/kvm/kvm-cpu.c
 +++ b/tools/kvm/kvm-cpu.c
 @@ -160,6 +160,25 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
   goto exit_kvm;
   case KVM_EXIT_SHUTDOWN:
   goto exit_kvm;
 + case KVM_EXIT_SYSTEM_EVENT:
 + /*
 +  * Print the type of system event and
 +  * treat all system events as shutdown request.
 +  */
 + switch (cpu-kvm_run-system_event.type) {
 + case KVM_SYSTEM_EVENT_SHUTDOWN:
 + printf(  # Info: shutdown system event\n);
 + break;
 + case KVM_SYSTEM_EVENT_RESET:
 + printf(  # Info: reset system event\n);
 + break;
 + default:
 + printf(  # Warning: unknown system event 
 type=%d\n,
 +cpu-kvm_run-system_event.type);
 + break;
 + };
 + printf(  # Info: exiting KVMTOOL\n);
 + goto exit_kvm;
   default: {
   bool ret;
  
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 12/15] arm/arm64: KVM: add virtual GICv3 distributor emulation

2014-09-05 Thread Andre Przywara
Hi wanghaibin,

On 05/09/14 04:28, wanghaibin wrote:
 On 2014/8/21 21:06, Andre Przywara wrote:
 
 
 +void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
 +{
 +struct kvm *kvm = vcpu-kvm;
 +struct kvm_vcpu *c_vcpu;
 +struct vgic_dist *dist = kvm-arch.vgic;
 +u16 target_cpus;
 +u64 mpidr, mpidr_h, mpidr_l;
 +int sgi, mode, c, vcpu_id;
 +int updated = 0;
 +
 +vcpu_id = vcpu-vcpu_id;
 +
 +sgi = (reg  24)  0xf;
 +mode = (reg  40)  0x1;
 +target_cpus = reg  0x;
 +mpidr = ((reg  48)  0xff)  MPIDR_LEVEL_SHIFT(3);
 +mpidr |= ((reg  32)  0xff)  MPIDR_LEVEL_SHIFT(2);
 +mpidr |= ((reg  16)  0xff)  MPIDR_LEVEL_SHIFT(1);
 +mpidr = ~MPIDR_LEVEL_MASK;
 +
 
 +/*
 + * We take the dist lock here, because we come from the sysregs
 + * code path and not from MMIO (where this is already done)
 + */
 +spin_lock(dist-lock);
 +kvm_for_each_vcpu(c, c_vcpu, kvm) {
 
 
 Hi, Andre, there is a suggestion. Move the
 
 +if (target_cpus == 0)
 +break;
 
 code, out the  kvm_for_each_vcpu loop, Like :
 
 
   if (!mode  target_cpus == 0)   /* the judgement do not need judge in 
 kvm_for_each_vcpu loop */
   return;

I am not so much concerned about someone actually sending a SGI to
no-one, but the code is there to stop the loop after the only CPU has
been serviced.
...

   spin_lock(dist-lock);
   kvm_for_each_vcpu(c, c_vcpu, kvm) {
 
 +if (mode  c == vcpu_id)   /* not to myself */
 +continue;
 +if (!mode) {
 +mpidr_h = kvm_vcpu_get_mpidr(c_vcpu);
 +mpidr_l = MPIDR_AFFINITY_LEVEL(mpidr_h, 0);
 +mpidr_h = ~MPIDR_LEVEL_MASK;
 +if (mpidr != mpidr_h)
 +continue;
 +if (!(target_cpus  BIT(mpidr_l)))
 +continue;
 +target_cpus = ~BIT(mpidr_l);

Here the CPU bit is removed from target_cpus. The idea is that most of
the time we trigger a SGI for a single CPU only, so there is no need to
further iterate through all VCPUs once we found the first and only one.
That's why I check target_cpus inside the loop.

Regards,
Andre.

 +}
 +/* Flag the SGI as pending */
 +vgic_dist_irq_set(c_vcpu, sgi);
 +updated = 1;
 +kvm_debug(SGI%d from CPU%d to CPU%d\n, sgi, vcpu_id, c);
 +}
 +if (updated)
 +vgic_update_state(vcpu-kvm);
 +spin_unlock(dist-lock);
 +if (updated)
 +vgic_kick_vcpus(vcpu-kvm);
 +}
 +
 +
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/4] kvmtool: ARM: Use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target cpu

2014-08-29 Thread Andre Przywara
(resent, that was the wrong account before ...)

Hi Anup,

On 26/08/14 10:22, Anup Patel wrote:
 Instead, of trying out each and every target type we should
 use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target type
 for KVM ARM/ARM64.
 
 If KVM_ARM_PREFERRED_TARGET vm ioctl fails then we fallback to
 old method of trying all known target types.

So as the algorithm currently works, it does not give us much
improvement over the current behaviour. We still need to list each
supported MPIDR both in kvmtool and in the kernel.
Looking more closely at the code, beside the target id we only need the
kvm_target_arm[] list for the compatible string and the init() function.
The latter is (currently) the same for all supported type, so we could
use that as a standard fallback function.
The compatible string seems to be completely ignored by the ARM64
kernel, so we could as well pass arm,armv8 all the time.
In ARM(32) kernels we seem to not make any real use of it for CPUs which
we care for (with virtualisation extensions).

So what about the following:
We keep the list as it is, but not extend it for future CPUs, expect
those in need for a special compatible string or a specific init
function. Instead we rely on PREFFERED_TARGET for all current and
upcoming CPUs (meaning unsupported CPUs must use a 3.12 kernel or higher).
If PREFERRED_TARGET works, we scan the list anyway (to find CPUs needing
special treatment), but on failure of finding something in the list we
just go ahead:
- with the target ID the kernel returned,
- an arm,armv8 compatible string (for arm64, not sure about arm) and
- call the standard kvmtool init function

This should relief us from the burden of adding each supported CPU to
kvmtool.

Does that make sense of am I missing something?
I will hack something up to prove that it works.

Also there is now a race on big.LITTLE systems: if the PREFERRED_TARGET
ioctl is executed on one cluster, while the KVM_ARM_VCPU_INIT call is
done on another core with a different MPIDR, then the kernel will refuse
to init the CPU. I don't know of a good solution for this (except the
sledgehammer pinning with sched_setaffinity to the current core, which
is racy, too, but should at least work somehow ;-)
Any ideas?

 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/kvm-cpu.c |   46 +++---
  1 file changed, 35 insertions(+), 11 deletions(-)
 
 diff --git a/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c
 index aeaa4cf..c010e9c 100644
 --- a/tools/kvm/arm/kvm-cpu.c
 +++ b/tools/kvm/arm/kvm-cpu.c
 @@ -34,6 +34,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   struct kvm_cpu *vcpu;
   int coalesced_offset, mmap_size, err = -1;
   unsigned int i;
 + struct kvm_vcpu_init preferred_init;
   struct kvm_vcpu_init vcpu_init = {
   .features = ARM_VCPU_FEATURE_FLAGS(kvm, cpu_id)
   };
 @@ -55,20 +56,42 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   if (vcpu-kvm_run == MAP_FAILED)
   die(unable to mmap vcpu fd);
  
 - /* Find an appropriate target CPU type. */
 - for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 - if (!kvm_arm_targets[i])
 - continue;
 - target = kvm_arm_targets[i];
 - vcpu_init.target = target-id;
 + /*
 +  * If preferred target ioctl successful then use preferred target
 +  * else try each and every target type.
 +  */
 + err = ioctl(kvm-vm_fd, KVM_ARM_PREFERRED_TARGET, preferred_init);
 + if (!err) {
 + /* Match preferred target CPU type. */
 + target = NULL;
 + for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 + if (!kvm_arm_targets[i])
 + continue;
 + if (kvm_arm_targets[i]-id == preferred_init.target) {
 + target = kvm_arm_targets[i];
 + break;
 + }
 + }
 +
 + vcpu_init.target = preferred_init.target;
   err = ioctl(vcpu-vcpu_fd, KVM_ARM_VCPU_INIT, vcpu_init);
 - if (!err)
 - break;
 + if (err || target-init(vcpu))
 + die(Unable to initialise vcpu for preferred target);

So that segfaults if the CPU is not in kvmtools list (as target is still
NULL). In the current implementation we should bail out (but better use
the algorithm described above).

Also these two line can be moved outside of the loop and joined with the
last two lines from the else clause ...

 + } else {
 + /* Find an appropriate target CPU type. */
 + for (i = 0; i  ARRAY_SIZE(kvm_arm_targets); ++i) {
 + if (!kvm_arm_targets[i])
 + continue;
 +   

Re: [PATCH v2 4/4] kvmtool: ARM/ARM64: Provide PSCI-0.2 to guest when KVM supports it

2014-08-29 Thread Andre Przywara
Hi Anup,

On 26/08/14 10:22, Anup Patel wrote:
 If in-kernel KVM support PSCI-0.2 emulation then we should set
 KVM_ARM_VCPU_PSCI_0_2 feature for each guest VCPU and also
 provide arm,psci-0.2,arm,psci as PSCI compatible string.
 
 This patch updates kvm_cpu__arch_init() and setup_fdt() as
 per above.
 
 Signed-off-by: Pranavkumar Sawargaonkar pranavku...@linaro.org
 Signed-off-by: Anup Patel anup.pa...@linaro.org
 ---
  tools/kvm/arm/fdt.c |   39 +--
  tools/kvm/arm/kvm-cpu.c |5 +
  2 files changed, 38 insertions(+), 6 deletions(-)
 
 diff --git a/tools/kvm/arm/fdt.c b/tools/kvm/arm/fdt.c
 index 186a718..93849cf2 100644
 --- a/tools/kvm/arm/fdt.c
 +++ b/tools/kvm/arm/fdt.c
 @@ -13,6 +13,7 @@
  #include linux/byteorder.h
  #include linux/kernel.h
  #include linux/sizes.h
 +#include linux/psci.h
  
  static char kern_cmdline[COMMAND_LINE_SIZE];
  
 @@ -162,12 +163,38 @@ static int setup_fdt(struct kvm *kvm)
  
   /* PSCI firmware */
   _FDT(fdt_begin_node(fdt, psci));
 - _FDT(fdt_property_string(fdt, compatible, arm,psci));
 - _FDT(fdt_property_string(fdt, method, hvc));
 - _FDT(fdt_property_cell(fdt, cpu_suspend, KVM_PSCI_FN_CPU_SUSPEND));
 - _FDT(fdt_property_cell(fdt, cpu_off, KVM_PSCI_FN_CPU_OFF));
 - _FDT(fdt_property_cell(fdt, cpu_on, KVM_PSCI_FN_CPU_ON));
 - _FDT(fdt_property_cell(fdt, migrate, KVM_PSCI_FN_MIGRATE));
 + if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
 + const char compatible[] = arm,psci-0.2\0arm,psci;
 + _FDT(fdt_property(fdt, compatible,
 +   compatible, sizeof(compatible)));
 + _FDT(fdt_property_string(fdt, method, hvc));
 + if (kvm-cfg.arch.aarch32_guest) {
 + _FDT(fdt_property_cell(fdt, cpu_suspend,
 + PSCI_0_2_FN_CPU_SUSPEND));
 + _FDT(fdt_property_cell(fdt, cpu_off,
 + PSCI_0_2_FN_CPU_OFF));
 + _FDT(fdt_property_cell(fdt, cpu_on,
 + PSCI_0_2_FN_CPU_ON));
 + _FDT(fdt_property_cell(fdt, migrate,
 + PSCI_0_2_FN_MIGRATE));
 + } else {
 + _FDT(fdt_property_cell(fdt, cpu_suspend,
 + PSCI_0_2_FN64_CPU_SUSPEND));
 + _FDT(fdt_property_cell(fdt, cpu_off,
 + PSCI_0_2_FN_CPU_OFF));
 + _FDT(fdt_property_cell(fdt, cpu_on,
 + PSCI_0_2_FN64_CPU_ON));
 + _FDT(fdt_property_cell(fdt, migrate,
 + PSCI_0_2_FN64_MIGRATE));
 + }
 + } else {
 + _FDT(fdt_property_string(fdt, compatible, arm,psci));
 + _FDT(fdt_property_string(fdt, method, hvc));
 + _FDT(fdt_property_cell(fdt, cpu_suspend, 
 KVM_PSCI_FN_CPU_SUSPEND));
 + _FDT(fdt_property_cell(fdt, cpu_off, KVM_PSCI_FN_CPU_OFF));
 + _FDT(fdt_property_cell(fdt, cpu_on, KVM_PSCI_FN_CPU_ON));
 + _FDT(fdt_property_cell(fdt, migrate, KVM_PSCI_FN_MIGRATE));
 + }

I guess this could be simplified much by defining three arrays with the
respective function IDs and setting a pointer to the right one here.
Then there would still be only one set of _FDT() calls, which reference
this pointer. Like:
uint32_t *psci_fn_ids;
...
if (KVM_CAP_ARM_PSCI_0_2) {
if (aarch32_guest)
psci_fn_ids = psci_0_2_fn_ids;
else
psci_fn_ids = psci_0_2_fn64_ids;
} else
psci_fn_ids = psci_0_1_fn_ids;
_FDT(fdt_property_cell(fdt, cpu_suspend, psci_fn_ids[0]));
_FDT(fdt_property_cell(fdt, cpu_off, psci_fn_ids[1]));
...

Also I wonder if we actually need those different IDs. The binding doc
says that Linux' PSCI 0.2 code ignores them altogether, only using them
if the arm,psci branch of the compatible string is actually used (on
kernels not supporting PSCI 0.2)
So can't we just always pass the PSCI 0.1 numbers in here?
That would restrict this whole patch to just changing the compatible
string, right?

Regards,
Andre.

   _FDT(fdt_end_node(fdt));
  
   /* Finalise. */
 diff --git a/tools/kvm/arm/kvm-cpu.c b/tools/kvm/arm/kvm-cpu.c
 index c010e9c..0637e9a 100644
 --- a/tools/kvm/arm/kvm-cpu.c
 +++ b/tools/kvm/arm/kvm-cpu.c
 @@ -56,6 +56,11 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, 
 unsigned long cpu_id)
   if (vcpu-kvm_run == MAP_FAILED)
   die(unable to mmap vcpu fd);
  
 + /* Set KVM_ARM_VCPU_PSCI_0_2 if available */
 + if (kvm__supports_extension(kvm, KVM_CAP_ARM_PSCI_0_2)) {
 + vcpu_init.features[0] |= (1UL  KVM_ARM_VCPU_PSCI_0_2);
 + }
 +
   /*
* If preferred 

Re: [PATCH v2 1/4] kvmtool: ARM: Use KVM_ARM_PREFERRED_TARGET vm ioctl to determine target cpu

2014-08-29 Thread Andre Przywara

On 29/08/14 17:17, Will Deacon wrote:
 On Fri, Aug 29, 2014 at 10:10:52AM +0100, Andre Przywara wrote:
 (resent, that was the wrong account before ...)

 Aha, and now your true identity has been revealed to all! Nice try Andre...
 or should I say, Rienhard?

Psst, don't give Google funny ideas about this (now very secret)
relationship ;-)

Cheers,
Andre R P.

-- IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered 
in England  Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, 
Registered in England  Wales, Company No:  2548782

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 06/15] arm/arm64: KVM: make the maximum number of vCPUs a per-VM value

2014-08-21 Thread Andre Przywara
Currently the maximum number of vCPUs supported is a global value
limited by the used GIC model. GICv3 will lift this limit, but we
still need to observe it for guests using GICv2.
So the maximum number of vCPUs is per-VM value, depending on the
GIC model the guest uses.
Store and check the value in struct kvm_arch, but keep it down to
8 for now.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/include/asm/kvm_host.h   |1 +
 arch/arm/kvm/arm.c|6 ++
 arch/arm64/include/asm/kvm_host.h |3 +++
 virt/kvm/arm/vgic-v2.c|5 +
 virt/kvm/arm/vgic-v3.c|6 ++
 5 files changed, 21 insertions(+)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index cf99ad0..0638419 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -67,6 +67,7 @@ struct kvm_arch {
 
/* Interrupt controller */
struct vgic_distvgic;
+   int max_vcpus;
 };
 
 #define KVM_NR_MEM_OBJS 40
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 157e1b6..190f05f 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -142,6 +142,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
/* Mark the initial VMID generation invalid */
kvm-arch.vmid_gen = 0;
+   kvm-arch.max_vcpus = CONFIG_KVM_ARM_MAX_VCPUS;
 
return ret;
 out_free_stage2_pgd:
@@ -223,6 +224,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, 
unsigned int id)
int err;
struct kvm_vcpu *vcpu;
 
+   if (id = kvm-arch.max_vcpus) {
+   err = -EINVAL;
+   goto out;
+   }
+
vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
if (!vcpu) {
err = -ENOMEM;
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 017fbae..a325161 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -58,6 +58,9 @@ struct kvm_arch {
/* VTTBR value associated with above pgd and vmid */
u64vttbr;
 
+   /* The maximum number of vCPUs depends on the used GIC model */
+   int max_vcpus;
+
/* Interrupt controller */
struct vgic_distvgic;
 
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 90947c6..c7362ff 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -177,11 +177,16 @@ static struct vgic_params vgic_v2_params;
 static bool vgic_v2_init_emul(struct kvm *kvm, int type)
 {
struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+   int nr_vcpus;
 
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
+   nr_vcpus = atomic_read(kvm-online_vcpus);
+   if (nr_vcpus  8)
+   return false;
vm_ops-get_lr = vgic_v2_get_lr;
vm_ops-set_lr = vgic_v2_set_lr;
+   kvm-arch.max_vcpus = 8;
return true;
}
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index a38339e..86e8b99 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -171,11 +171,17 @@ static const struct vgic_ops vgic_v3_ops = {
 static bool vgic_v3_init_emul_compat(struct kvm *kvm, int type)
 {
struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+   int nr_vcpus;
 
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
+   nr_vcpus = atomic_read(kvm-online_vcpus);
+   if (nr_vcpus  8)
+   return false;
+
vm_ops-get_lr = vgic_v3_get_lr;
vm_ops-set_lr = vgic_v3_set_lr;
+   kvm-arch.max_vcpus = 8;
return true;
}
return false;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 12/15] arm/arm64: KVM: add virtual GICv3 distributor emulation

2014-08-21 Thread Andre Przywara
With everything separated and prepared, we implement a model of a
GICv3 distributor and redistributors by using the existing framework
to provide handler functions for each register group.
Currently we limit the emulation to a model enforcing a single
security state, with SRE==1 (forcing system register access) and
ARE==1 (allowing more than 8 VCPUs).
We share some of functions provided for GICv2 emulation, but take
the different ways of addressing (v)CPUs into account.
Save and restore is currently not implemented.

Similar to the split-off GICv2 specific code, the new emulation code
goes into a new file (vgic-v3-emul.c).

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/kvm/Makefile|1 +
 include/kvm/arm_vgic.h |   11 +-
 include/linux/irqchip/arm-gic-v3.h |   26 ++
 include/linux/kvm_host.h   |1 +
 include/uapi/linux/kvm.h   |1 +
 virt/kvm/arm/vgic-v3-emul.c|  896 
 virt/kvm/arm/vgic.c|   11 +-
 virt/kvm/arm/vgic.h|3 +
 virt/kvm/kvm_main.c|3 +
 9 files changed, 950 insertions(+), 3 deletions(-)
 create mode 100644 virt/kvm/arm/vgic-v3-emul.c

diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index d957353..4e6e09e 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -24,5 +24,6 @@ kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3-emul.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o
 kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 8aa8482..3b164ee 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -151,7 +151,11 @@ struct vgic_dist {
 
/* Distributor and vcpu interface mapping in the guest */
phys_addr_t vgic_dist_base;
-   phys_addr_t vgic_cpu_base;
+   /* GICv2 and GICv3 use different mapped register blocks */
+   union {
+   phys_addr_t vgic_cpu_base;
+   phys_addr_t vgic_redist_base;
+   };
 
/* Distributor enabled */
u32 enabled;
@@ -176,6 +180,10 @@ struct vgic_dist {
 
/* Target CPU for each IRQ */
u8  *irq_spi_cpu;
+
+   /* Target MPIDR for each IRQ (needed for GICv3 IROUTERn) only */
+   u32 *irq_spi_mpidr;
+
struct vgic_bitmap  *irq_spi_target;
 
/* Bitmap indicating which CPU has something pending */
@@ -253,6 +261,7 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
bool level);
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 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);
diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index 03a4ea3..6a649bc 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -33,6 +33,7 @@
 #define GICD_SETSPI_SR 0x0050
 #define GICD_CLRSPI_SR 0x0058
 #define GICD_SEIR  0x0068
+#define GICD_IGROUPR   0x0080
 #define GICD_ISENABLER 0x0100
 #define GICD_ICENABLER 0x0180
 #define GICD_ISPENDR   0x0200
@@ -41,14 +42,31 @@
 #define GICD_ICACTIVER 0x0380
 #define GICD_IPRIORITYR0x0400
 #define GICD_ICFGR 0x0C00
+#define GICD_IGRPMODR  0x0D00
+#define GICD_NSACR 0x0E00
 #define GICD_IROUTER   0x6000
+#define GICD_IDREGS0xFFD0
 #define GICD_PIDR2 0xFFE8
 
+/*
+ * Non-ARE distributor registers, needed to provide the RES0
+ * semantics for KVM's emulated GICv3
+ */
+#define GICD_ITARGETSR 0x0800
+#define GICD_SGIR  0x0F00
+#define GICD_CPENDSGIR 0x0F10
+#define GICD_SPENDSGIR 0x0F20
+
+
 #define GICD_CTLR_RWP  (1U  31)
+#define GICD_CTLR_DS   (1U  6)
 #define GICD_CTLR_ARE_NS   (1U  4)
 #define GICD_CTLR_ENABLE_G1A   (1U  1)
 #define GICD_CTLR_ENABLE_G1(1U  0)
 
+#define GICD_TYPER_LPIS(1U  17)
+#define GICD_TYPER_MBIS(1U  16)
+
 #define GICD_IROUTER_SPI_MODE_ONE  (0U  31)
 #define GICD_IROUTER_SPI_MODE_ANY  (1U  31)
 
@@ -56,6 +74,8 @@
 #define

[PATCH v2 14/15] arm/arm64: KVM: enable kernel side of GICv3 emulation

2014-08-21 Thread Andre Przywara
With all the necessary GICv3 emulation code in place, we can now
connect the code to the GICv3 backend in the kernel.
The LR register handling is different depending on the emulated GIC
model, so provide different implementations for each.
Also allow non-v2-compatible GICv3 implementations (which don't
provide MMIO regions for the virtual CPU interface in the DT), but
restrict those hosts to use GICv3 guests only.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic-v3.c |  168 +++-
 virt/kvm/arm/vgic.c|2 +
 2 files changed, 127 insertions(+), 43 deletions(-)

diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 8af8037..c4e2f13 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -34,6 +34,7 @@
 #define GICH_LR_VIRTUALID  (0x3ffUL  0)
 #define GICH_LR_PHYSID_CPUID_SHIFT (10)
 #define GICH_LR_PHYSID_CPUID   (7UL  GICH_LR_PHYSID_CPUID_SHIFT)
+#define ICH_LR_VIRTUALID_MASK  (BIT_ULL(32) - 1)
 
 /*
  * LRs are stored in reverse order in memory. make sure we index them
@@ -43,7 +44,35 @@
 
 static u32 ich_vtr_el2;
 
-static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
+static u64 sync_lr_val(u8 state)
+{
+   u64 lr_val = 0;
+
+   if (state  LR_STATE_PENDING)
+   lr_val |= ICH_LR_PENDING_BIT;
+   if (state  LR_STATE_ACTIVE)
+   lr_val |= ICH_LR_ACTIVE_BIT;
+   if (state  LR_EOI_INT)
+   lr_val |= ICH_LR_EOI;
+
+   return lr_val;
+}
+
+static u8 sync_lr_state(u64 lr_val)
+{
+   u8 state = 0;
+
+   if (lr_val  ICH_LR_PENDING_BIT)
+   state |= LR_STATE_PENDING;
+   if (lr_val  ICH_LR_ACTIVE_BIT)
+   state |= LR_STATE_ACTIVE;
+   if (lr_val  ICH_LR_EOI)
+   state |= LR_EOI_INT;
+
+   return state;
+}
+
+static struct vgic_lr vgic_v2_on_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 {
struct vgic_lr lr_desc;
u64 val = vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
@@ -53,30 +82,53 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu 
*vcpu, int lr)
lr_desc.source  = (val  GICH_LR_PHYSID_CPUID_SHIFT)  0x7;
else
lr_desc.source = 0;
-   lr_desc.state   = 0;
+   lr_desc.state   = sync_lr_state(val);
 
-   if (val  ICH_LR_PENDING_BIT)
-   lr_desc.state |= LR_STATE_PENDING;
-   if (val  ICH_LR_ACTIVE_BIT)
-   lr_desc.state |= LR_STATE_ACTIVE;
-   if (val  ICH_LR_EOI)
-   lr_desc.state |= LR_EOI_INT;
+   return lr_desc;
+}
+
+static struct vgic_lr vgic_v3_on_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
+{
+   struct vgic_lr lr_desc;
+   u64 val = vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
+
+   lr_desc.irq = val  ICH_LR_VIRTUALID_MASK;
+   lr_desc.source  = 0;
+   lr_desc.state   = sync_lr_state(val);
 
return lr_desc;
 }
 
-static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
-  struct vgic_lr lr_desc)
+static void vgic_v3_on_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
+struct vgic_lr lr_desc)
 {
-   u64 lr_val = (((u32)lr_desc.source  GICH_LR_PHYSID_CPUID_SHIFT) |
- lr_desc.irq);
+   u64 lr_val;
 
-   if (lr_desc.state  LR_STATE_PENDING)
-   lr_val |= ICH_LR_PENDING_BIT;
-   if (lr_desc.state  LR_STATE_ACTIVE)
-   lr_val |= ICH_LR_ACTIVE_BIT;
-   if (lr_desc.state  LR_EOI_INT)
-   lr_val |= ICH_LR_EOI;
+   lr_val = lr_desc.irq;
+
+   /*
+* currently all guest IRQs are Group1, as Group0 would result
+* in a FIQ in the guest, which it wouldn't expect.
+* Eventually we want to make this configurable, so we may revisit
+* this in the future.
+*/
+   lr_val |= ICH_LR_GROUP;
+
+   lr_val |= sync_lr_val(lr_desc.state);
+
+   vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val;
+}
+
+static void vgic_v2_on_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
+struct vgic_lr lr_desc)
+{
+   u64 lr_val;
+
+   lr_val = lr_desc.irq;
+
+   lr_val |= (u32)lr_desc.source  GICH_LR_PHYSID_CPUID_SHIFT;
+
+   lr_val |= sync_lr_val(lr_desc.state);
 
vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val;
 }
@@ -145,9 +197,8 @@ static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct 
vgic_vmcr *vmcrp)
 
 static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
-   struct vgic_v3_cpu_if *vgic_v3;
+   struct vgic_v3_cpu_if *vgic_v3 = vcpu-arch.vgic_cpu.vgic_v3;
 
-   vgic_v3 = vcpu-arch.vgic_cpu.vgic_v3;
/*
 * By forcing VMCR to zero, the GIC will restore the binary
 * points to their reset values. Anything else resets to zero
@@ -155,7 +206,14 @@ static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 */
vgic_v3-vgic_vmcr

[PATCH v2 08/15] arm/arm64: KVM: refactor MMIO accessors

2014-08-21 Thread Andre Przywara
The MMIO accessors for GICD_I[CS]ENABLER, GICD_I[CS]PENDR and
GICD_ICFGR behave very similiar in GICv3, although the way the
affected vCPU is determined differs.
Factor out a generic, backend-facing implementation and use small
wrappers in the current GICv2 emulation to ease code sharing later.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   93 ---
 1 file changed, 52 insertions(+), 41 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 5e0bc24..e8f92b2 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -418,35 +418,54 @@ static bool handle_mmio_raz_wi(struct kvm_vcpu *vcpu,
return false;
 }
 
-static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
-  struct kvm_exit_mmio *mmio,
-  phys_addr_t offset)
+static bool vgic_handle_enable_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
+  phys_addr_t offset, int vcpu_id, int access)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_enabled,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
+   u32 *reg;
+   int mode = ACCESS_READ_VALUE | access;
+   struct kvm_vcpu *target_vcpu = kvm_get_vcpu(kvm, vcpu_id);
+
+   reg = vgic_bitmap_get_reg(kvm-arch.vgic.irq_enabled, vcpu_id, offset);
+   vgic_reg_access(mmio, reg, offset, mode);
if (mmio-is_write) {
-   vgic_update_state(vcpu-kvm);
+   if (access  ACCESS_WRITE_CLEARBIT) {
+   if (offset  4) /* Force SGI enabled */
+   *reg |= 0x;
+   vgic_retire_disabled_irqs(target_vcpu);
+   }
+   vgic_update_state(kvm);
return true;
}
 
return false;
 }
 
+static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
+  struct kvm_exit_mmio *mmio,
+  phys_addr_t offset)
+{
+   return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
+ vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
+}
+
 static bool handle_mmio_clear_enable_reg(struct kvm_vcpu *vcpu,
 struct kvm_exit_mmio *mmio,
 phys_addr_t offset)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_enabled,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
+   return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
+ vcpu-vcpu_id, ACCESS_WRITE_CLEARBIT);
+}
+
+static bool vgic_handle_pending_reg(struct kvm *kvm, struct kvm_exit_mmio 
*mmio,
+   phys_addr_t offset, int vcpu_id, int access)
+{
+   u32 *reg;
+   int mode = ACCESS_READ_VALUE | access;
+
+   reg = vgic_bitmap_get_reg(kvm-arch.vgic.irq_state, vcpu_id, offset);
+   vgic_reg_access(mmio, reg, offset, mode);
if (mmio-is_write) {
-   if (offset  4) /* Force SGI enabled */
-   *reg |= 0x;
-   vgic_retire_disabled_irqs(vcpu);
-   vgic_update_state(vcpu-kvm);
+   vgic_update_state(kvm);
return true;
}
 
@@ -457,31 +476,16 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu 
*vcpu,
struct kvm_exit_mmio *mmio,
phys_addr_t offset)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_state,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
-   if (mmio-is_write) {
-   vgic_update_state(vcpu-kvm);
-   return true;
-   }
-
-   return false;
+   return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
+  vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
 }
 
 static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
  struct kvm_exit_mmio *mmio,
  phys_addr_t offset)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_state,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
-   if (mmio-is_write) {
-   vgic_update_state(vcpu-kvm);
-   return true;
-   }
-
+   return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
+  vcpu

[PATCH v2 15/15] arm/arm64: KVM: allow userland to request a virtual GICv3

2014-08-21 Thread Andre Przywara
With everything in place we allow userland to request the kernel
using a virtual GICv3 in the guest, which finally lifts the 8 vCPU
limit for a guest.
Also we provide the necessary support for guests setting the memory
addresses for the virtual distributor and redistributors.
This requires some userland code to make use of that feature and
explicitly ask for a virtual GICv3.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/include/uapi/asm/kvm.h |7 ++
 include/kvm/arm_vgic.h|4 ++--
 virt/kvm/arm/vgic-v3-emul.c   |3 +++
 virt/kvm/arm/vgic.c   |   46 ++---
 4 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index 5513de4..9a62081 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -77,6 +77,13 @@ struct kvm_regs {
 #define KVM_VGIC_V2_DIST_SIZE  0x1000
 #define KVM_VGIC_V2_CPU_SIZE   0x2000
 
+/* Supported VGICv3 address types  */
+#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST   3
+
+#define KVM_VGIC_V3_DIST_SIZE  SZ_64K
+#define KVM_VGIC_V3_REDIST_SIZE(2 * SZ_64K)
+
 #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
 #define KVM_ARM_VCPU_PSCI_0_2  2 /* CPU uses PSCI v0.2 */
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3b164ee..82e00a5 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -35,8 +35,8 @@
 #define VGIC_MAX_IRQS  1024
 
 /* Sanity checks... */
-#if (KVM_MAX_VCPUS  8)
-#error Invalid number of CPU interfaces
+#if (KVM_MAX_VCPUS  255)
+#error Too many KVM VCPUs, the VGIC only supports up to 255 VCPUs for now
 #endif
 
 #if (VGIC_NR_IRQS_LEGACY  31)
diff --git a/virt/kvm/arm/vgic-v3-emul.c b/virt/kvm/arm/vgic-v3-emul.c
index ac5c5ee..d4d9fe4 100644
--- a/virt/kvm/arm/vgic-v3-emul.c
+++ b/virt/kvm/arm/vgic-v3-emul.c
@@ -874,6 +874,9 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
case KVM_VGIC_V2_ADDR_TYPE_DIST:
case KVM_VGIC_V2_ADDR_TYPE_CPU:
return -ENXIO;
+   case KVM_VGIC_V3_ADDR_TYPE_DIST:
+   case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+   return 0;
}
break;
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index b1bcb6d..f13ab4e 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1567,7 +1567,7 @@ static int vgic_ioaddr_assign(struct kvm *kvm, 
phys_addr_t *ioaddr,
 /**
  * kvm_vgic_addr - set or get vgic VM base addresses
  * @kvm:   pointer to the vm struct
- * @type:  the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
  * @addr:  pointer to address value
  * @write: if true set the address in the VM address space, if false read the
  *  address
@@ -1581,29 +1581,49 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, 
u64 *addr, bool write)
 {
int r = 0;
struct vgic_dist *vgic = kvm-arch.vgic;
+   int type_needed;
+   phys_addr_t *addr_ptr, block_size;
 
mutex_lock(kvm-lock);
switch (type) {
case KVM_VGIC_V2_ADDR_TYPE_DIST:
-   if (write) {
-   r = vgic_ioaddr_assign(kvm, vgic-vgic_dist_base,
-  *addr, KVM_VGIC_V2_DIST_SIZE);
-   } else {
-   *addr = vgic-vgic_dist_base;
-   }
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+   addr_ptr = vgic-vgic_dist_base;
+   block_size = KVM_VGIC_V2_DIST_SIZE;
break;
case KVM_VGIC_V2_ADDR_TYPE_CPU:
-   if (write) {
-   r = vgic_ioaddr_assign(kvm, vgic-vgic_cpu_base,
-  *addr, KVM_VGIC_V2_CPU_SIZE);
-   } else {
-   *addr = vgic-vgic_cpu_base;
-   }
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+   addr_ptr = vgic-vgic_cpu_base;
+   block_size = KVM_VGIC_V2_CPU_SIZE;
break;
+#ifdef CONFIG_ARM_GIC_V3
+   case KVM_VGIC_V3_ADDR_TYPE_DIST:
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+   addr_ptr = vgic-vgic_dist_base;
+   block_size = KVM_VGIC_V3_DIST_SIZE;
+   break;
+   case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+   addr_ptr = vgic-vgic_redist_base;
+   block_size = KVM_VGIC_V3_REDIST_SIZE;
+   break;
+#endif
default:
r = -ENODEV;
+   goto out;
}
 
+   if (vgic-vgic_model

[PATCH v2 04/15] arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones

2014-08-21 Thread Andre Przywara
Some GICv3 registers can and will be accessed as 64 bit registers.
Currently the register handling code can only deal with 32 bit
accesses, so we do two consecutive calls to cover this.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   48 +---
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 3b6f78d..bef9aa0 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -926,6 +926,48 @@ static bool vgic_validate_access(const struct vgic_dist 
*dist,
 }
 
 /*
+ * Call the respective handler function for the given range.
+ * We split up any 64 bit accesses into two consecutive 32 bit
+ * handler calls and merge the result afterwards.
+ */
+static bool call_range_handler(struct kvm_vcpu *vcpu,
+  struct kvm_exit_mmio *mmio,
+  unsigned long offset,
+  const struct mmio_range *range)
+{
+   u32 *data32 = (void *)mmio-data;
+   struct kvm_exit_mmio mmio32;
+   bool ret;
+
+   if (likely(mmio-len = 4))
+   return range-handle_mmio(vcpu, mmio, offset);
+
+   /*
+* We assume that any access greater than 4 bytes is actually
+* 8 bytes long, caused by a 64-bit access
+*/
+
+   mmio32.len = 4;
+   mmio32.is_write = mmio-is_write;
+
+   mmio32.phys_addr = mmio-phys_addr + 4;
+   if (mmio-is_write)
+   *(u32 *)mmio32.data = data32[1];
+   ret = range-handle_mmio(vcpu, mmio32, offset + 4);
+   if (!mmio-is_write)
+   data32[1] = *(u32 *)mmio32.data;
+
+   mmio32.phys_addr = mmio-phys_addr;
+   if (mmio-is_write)
+   *(u32 *)mmio32.data = data32[0];
+   ret |= range-handle_mmio(vcpu, mmio32, offset);
+   if (!mmio-is_write)
+   data32[0] = *(u32 *)mmio32.data;
+
+   return ret;
+}
+
+/*
  * vgic_handle_mmio_range - handle an in-kernel MMIO access
  * @vcpu:  pointer to the vcpu performing the access
  * @run:   pointer to the kvm_run structure
@@ -956,10 +998,10 @@ static bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, 
struct kvm_run *run,
spin_lock(vcpu-kvm-arch.vgic.lock);
offset -= range-base;
if (vgic_validate_access(dist, range, offset)) {
-   updated_state = range-handle_mmio(vcpu, mmio, offset);
+   updated_state = call_range_handler(vcpu, mmio, offset, range);
} else {
-   vgic_reg_access(mmio, NULL, offset,
-   ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
+   if (!mmio-is_write)
+   memset(mmio-data, 0, mmio-len);
updated_state = false;
}
spin_unlock(vcpu-kvm-arch.vgic.lock);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/15] arm/arm64: KVM: split GICv2 specific emulation code from vgic.c

2014-08-21 Thread Andre Przywara
vgic.c is currently a mixture of generic vGIC emulation code and
functions specific to emulating a GICv2. To ease the addition of
GICv3, split off strictly v2 specific parts into a new file
vgic-v2-emul.c.
A new header file vgic.h is introduced to allow separation and later
sharing of functions.

Signed-off-by: Andre Przywara andre.przyw...@arm.com

---
As the diff isn't always obvious here (and to aid eventual rebases),
here is a list of high-level changes done to the code:
* added new file to respective arm/arm64 Makefiles
* moved definitions and prototypes from vgic.c to vgic.h:
  - VGIC_ADDR_UNDEF
  - ACCESS_{READ,WRITE}_*
  - vgic_update_state()
  - vgic_kick_vcpus()
  - vgic_get_vmcr()
  - vgic_set_vmcr()
  - struct mmio_range {}
  - IS_IN_RANGE() macro
* removed static keyword and exported prototype in vgic.h:
  - vgic_bitmap_get_reg()
  - vgic_bitmap_set_irq_val()
  - vgic_bitmap_get_shared_map()
  - vgic_bytemap_get_reg()
  - vgic_dist_irq_set()
  - vgic_dist_irq_clear()
  - vgic_cpu_irq_clear()
  - vgic_reg_access()
  - handle_mmio_raz_wi()
  - vgic_handle_enable_reg()
  - vgic_handle_pending_reg()
  - vgic_handle_cfg_reg()
  - vgic_unqueue_irqs()
  - find_matching_range() (renamed to vgic_* to avoid namespace clutter)
  - vgic_handle_mmio_range()
  - vgic_update_state()
  - vgic_get_vmcr()
  - vgic_set_vmcr()
  - vgic_queue_irq()
  - vgic_kick_vcpus()
  - vgic_init_maps()
  - vgic_has_attr_regs()
  - vgic_set_common_attr()
  - vgic_get_common_attr()
  - vgic_destroy()
  - vgic_create()
* moved functions to vgic.h (static inline):
  - mmio_data_read()
  - mmio_data_write()
* moved GICv2 specific functions to vgic-v2-emul.c:
  - handle_mmio_misc()
  - handle_mmio_set_enable_reg()
  - handle_mmio_clear_enable_reg()
  - handle_mmio_set_pending_reg()
  - handle_mmio_clear_pending_reg()
  - handle_mmio_priority_reg()
  - vgic_get_target_reg()
  - vgic_set_target_reg()
  - handle_mmio_target_reg()
  - handle_mmio_cfg_reg()
  - handle_mmio_sgi_reg()
  - vgic_v2_unqueue_sgi()
  - read_set_clear_sgi_pend_reg()
  - write_set_clear_sgi_pend_reg()
  - handle_mmio_sgi_set()
  - handle_mmio_sgi_clear()
  - vgic_v2_handle_mmio()
  - vgic_get_sgi_sources()
  - vgic_dispatch_sgi()
  - vgic_v2_queue_sgi()
  - vgic_v2_init()
  - handle_cpu_mmio_misc()
  - handle_mmio_abpr()
  - handle_cpu_mmio_ident()
  - vgic_attr_regs_access()
  - vgic_has_attr() (renamed to vgic_v2_has_attr())
  - vgic_set_attr() (renamed to vgic_v2_set_attr())
  - vgic_get_attr() (renamed to vgic_v2_get_attr())
  - struct mmio_range vgic_dist_ranges[]
  - struct mmio_range vgic_cpu_ranges[]
  - struct kvm_device_ops kvm_arm_vgic_v2_ops {}
* moved content of init_emulation_ops() into separate function in vgic-v2-emul.c
---
 arch/arm/kvm/Makefile   |1 +
 arch/arm64/kvm/Makefile |1 +
 virt/kvm/arm/vgic-v2-emul.c |  796 +++
 virt/kvm/arm/vgic.c |  870 ++-
 virt/kvm/arm/vgic.h |  122 ++
 5 files changed, 960 insertions(+), 830 deletions(-)
 create mode 100644 virt/kvm/arm/vgic-v2-emul.c
 create mode 100644 virt/kvm/arm/vgic.h

diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index f7057ed..443b8be 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -22,4 +22,5 @@ obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
 obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
 obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
+obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
 obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 32a0961..d957353 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -21,6 +21,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o 
sys_regs_generic_v8.o
 
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v3-switch.o
diff --git a/virt/kvm/arm/vgic-v2-emul.c b/virt/kvm/arm/vgic-v2-emul.c
new file mode 100644
index 000..a6bfd75
--- /dev/null
+++ b/virt/kvm/arm/vgic-v2-emul.c
@@ -0,0 +1,796 @@
+/*
+ * Contains GICv2 specific emulation code, was in vgic.c before.
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier marc.zyng...@arm.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details

[PATCH v2 01/15] arm/arm64: KVM: rework MPIDR assignment and add accessors

2014-08-21 Thread Andre Przywara
The virtual MPIDR registers (containing topology information) for the
guest are currently mapped linearily to the vcpu_id. Improve this
mapping for arm64 by using three levels to not artificially limit the
number of vCPUs. Also add an accessor to later allow easier access to
a vCPU with a given MPIDR.
Use this new accessor in the PSCI emulation.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/include/asm/kvm_emulate.h   |2 +-
 arch/arm/include/asm/kvm_host.h  |2 ++
 arch/arm/kvm/arm.c   |   15 +++
 arch/arm/kvm/psci.c  |   15 ---
 arch/arm64/include/asm/kvm_emulate.h |3 ++-
 arch/arm64/include/asm/kvm_host.h|2 ++
 arch/arm64/kvm/sys_regs.c|   11 +--
 7 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/kvm_emulate.h 
b/arch/arm/include/asm/kvm_emulate.h
index 69b7469..18e45f7 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -159,7 +159,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu 
*vcpu)
 
 static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
 {
-   return vcpu-arch.cp15[c0_MPIDR];
+   return vcpu-arch.cp15[c0_MPIDR]  MPIDR_HWID_BITMASK;
 }
 
 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 6dfb404..cf99ad0 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -233,4 +233,6 @@ static inline void vgic_arch_setup(const struct vgic_params 
*vgic)
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
+struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 7d5065e..addb990 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -990,6 +990,21 @@ static void check_kvm_target_cpu(void *ret)
*(int *)ret = kvm_target_cpu();
 }
 
+struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
+{
+   unsigned long c_mpidr;
+   struct kvm_vcpu *vcpu;
+   int i;
+
+   mpidr = MPIDR_HWID_BITMASK;
+   kvm_for_each_vcpu(i, vcpu, kvm) {
+   c_mpidr = kvm_vcpu_get_mpidr(vcpu);
+   if (c_mpidr == mpidr)
+   return vcpu;
+   }
+   return NULL;
+}
+
 /**
  * Initialize Hyp-mode and memory mappings on all CPUs.
  */
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 09cf377..49f0992 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -21,6 +21,7 @@
 #include asm/cputype.h
 #include asm/kvm_emulate.h
 #include asm/kvm_psci.h
+#include asm/kvm_host.h
 
 /*
  * This is an implementation of the Power State Coordination Interface
@@ -65,25 +66,17 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
 static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 {
struct kvm *kvm = source_vcpu-kvm;
-   struct kvm_vcpu *vcpu = NULL, *tmp;
+   struct kvm_vcpu *vcpu = NULL;
wait_queue_head_t *wq;
unsigned long cpu_id;
unsigned long context_id;
-   unsigned long mpidr;
phys_addr_t target_pc;
-   int i;
 
-   cpu_id = *vcpu_reg(source_vcpu, 1);
+   cpu_id = *vcpu_reg(source_vcpu, 1)  MPIDR_HWID_BITMASK;
if (vcpu_mode_is_32bit(source_vcpu))
cpu_id = ~((u32) 0);
 
-   kvm_for_each_vcpu(i, tmp, kvm) {
-   mpidr = kvm_vcpu_get_mpidr(tmp);
-   if ((mpidr  MPIDR_HWID_BITMASK) == (cpu_id  
MPIDR_HWID_BITMASK)) {
-   vcpu = tmp;
-   break;
-   }
-   }
+   vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id);
 
/*
 * Make sure the caller requested a valid CPU and that the CPU is
diff --git a/arch/arm64/include/asm/kvm_emulate.h 
b/arch/arm64/include/asm/kvm_emulate.h
index fdc3e21..4b8d636 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -27,6 +27,7 @@
 #include asm/kvm_arm.h
 #include asm/kvm_mmio.h
 #include asm/ptrace.h
+#include asm/cputype.h
 
 unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, u8 reg_num);
 unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu);
@@ -179,7 +180,7 @@ static inline u8 kvm_vcpu_trap_get_fault(const struct 
kvm_vcpu *vcpu)
 
 static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
 {
-   return vcpu_sys_reg(vcpu, MPIDR_EL1);
+   return vcpu_sys_reg(vcpu, MPIDR_EL1)  MPIDR_HWID_BITMASK;
 }
 
 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index e10c45a..017fbae 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -244,4 +244,6 @@ static inline void vgic_arch_setup(const struct vgic_params 
*vgic)
}
 }
 
+struct kvm_vcpu *kvm_mpidr_to_vcpu

[PATCH v2 07/15] arm/arm64: KVM: make the value of ICC_SRE_EL1 a per-VM variable

2014-08-21 Thread Andre Przywara
ICC_SRE_EL1 is a system register allowing msr/mrs accesses to the
GIC CPU interface for EL1 (guests). Currently we force it to 0, but
for proper GICv3 support we have to allow guests to use it (depending
on their selected virtual GIC model).
So add ICC_SRE_EL1 to the list of saved/restored registers on a
world switch, but actually disallow a guest to change it by only
restoring a fixed, once-initialized value.
This value depends on the GIC model userland has chosen for a guest.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/kernel/asm-offsets.c |1 +
 arch/arm64/kvm/vgic-v3-switch.S |   14 +-
 include/kvm/arm_vgic.h  |1 +
 virt/kvm/arm/vgic-v3.c  |9 +++--
 4 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 9a9fce0..9d34486 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -140,6 +140,7 @@ int main(void)
   DEFINE(VGIC_V2_CPU_ELRSR,offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
   DEFINE(VGIC_V2_CPU_APR,  offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
   DEFINE(VGIC_V2_CPU_LR,   offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
+  DEFINE(VGIC_V3_CPU_SRE,  offsetof(struct vgic_cpu, vgic_v3.vgic_sre));
   DEFINE(VGIC_V3_CPU_HCR,  offsetof(struct vgic_cpu, vgic_v3.vgic_hcr));
   DEFINE(VGIC_V3_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr));
   DEFINE(VGIC_V3_CPU_MISR, offsetof(struct vgic_cpu, vgic_v3.vgic_misr));
diff --git a/arch/arm64/kvm/vgic-v3-switch.S b/arch/arm64/kvm/vgic-v3-switch.S
index d160469..617a012 100644
--- a/arch/arm64/kvm/vgic-v3-switch.S
+++ b/arch/arm64/kvm/vgic-v3-switch.S
@@ -148,17 +148,18 @@
  * x0: Register pointing to VCPU struct
  */
 .macro restore_vgic_v3_state
-   // Disable SRE_EL1 access. Necessary, otherwise
-   // ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens...
-   msr_s   ICC_SRE_EL1, xzr
-   isb
-
// Compute the address of struct vgic_cpu
add x3, x0, #VCPU_VGIC_CPU
 
// Restore all interesting registers
ldr w4, [x3, #VGIC_V3_CPU_HCR]
ldr w5, [x3, #VGIC_V3_CPU_VMCR]
+   ldr w25, [x3, #VGIC_V3_CPU_SRE]
+
+   msr_s   ICC_SRE_EL1, x25
+
+   // make sure SRE is valid before writing the other registers
+   isb
 
msr_s   ICH_HCR_EL2, x4
msr_s   ICH_VMCR_EL2, x5
@@ -244,9 +245,12 @@
dsb sy
 
// Prevent the guest from touching the GIC system registers
+   // if SRE isn't enabled for GICv3 emulation
+   cbnzx25, 1f
mrs_s   x5, ICC_SRE_EL2
and x5, x5, #~ICC_SRE_EL2_ENABLE
msr_s   ICC_SRE_EL2, x5
+1:
 .endm
 
 ENTRY(__save_vgic_v3_state)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 7e7c99e..8aa8482 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -199,6 +199,7 @@ struct vgic_v3_cpu_if {
 #ifdef CONFIG_ARM_GIC_V3
u32 vgic_hcr;
u32 vgic_vmcr;
+   u32 vgic_sre;   /* Restored only, change ignored */
u32 vgic_misr;  /* Saved only */
u32 vgic_eisr;  /* Saved only */
u32 vgic_elrsr; /* Saved only */
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 86e8b99..8af8037 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -145,15 +145,20 @@ static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, 
struct vgic_vmcr *vmcrp)
 
 static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+   struct vgic_v3_cpu_if *vgic_v3;
+
+   vgic_v3 = vcpu-arch.vgic_cpu.vgic_v3;
/*
 * By forcing VMCR to zero, the GIC will restore the binary
 * points to their reset values. Anything else resets to zero
 * anyway.
 */
-   vcpu-arch.vgic_cpu.vgic_v3.vgic_vmcr = 0;
+   vgic_v3-vgic_vmcr = 0;
+
+   vgic_v3-vgic_sre   = 0;
 
/* Get the show on the road... */
-   vcpu-arch.vgic_cpu.vgic_v3.vgic_hcr = ICH_HCR_EN;
+   vgic_v3-vgic_hcr = ICH_HCR_EN;
 }
 
 static const struct vgic_ops vgic_v3_ops = {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/15] arm/arm64: KVM: introduce per-VM ops

2014-08-21 Thread Andre Przywara
Currently we only have one virtual GIC model supported, so all guests
use the same emulation code. With the addition of another model we
end up with different guests using potentially different vGIC models,
so we have to split up some functions to be per VM.
Introduce a vgic_vm_ops struct to hold function pointers for those
functions that are different and provide the necessary code to
initialize them.
This includes functions that depend on the emulated GIC model only
and functions that depend on the combination of host and guest GIC.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 include/kvm/arm_vgic.h |   18 --
 virt/kvm/arm/vgic-v2.c |   17 +++--
 virt/kvm/arm/vgic-v3.c |   16 +++--
 virt/kvm/arm/vgic.c|   92 +++-
 4 files changed, 113 insertions(+), 30 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 4feac9a..7e7c99e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -99,8 +99,6 @@ struct vgic_vmcr {
 };
 
 struct vgic_ops {
-   struct vgic_lr  (*get_lr)(const struct kvm_vcpu *, int);
-   void(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
void(*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
u64 (*get_elrsr)(const struct kvm_vcpu *vcpu);
u64 (*get_eisr)(const struct kvm_vcpu *vcpu);
@@ -123,6 +121,17 @@ struct vgic_params {
unsigned intmaint_irq;
/* Virtual control interface base address */
void __iomem*vctrl_base;
+   bool (*init_emul)(struct kvm *kvm, int type);
+};
+
+struct vgic_vm_ops {
+   struct vgic_lr  (*get_lr)(const struct kvm_vcpu *, int);
+   void(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
+   bool(*handle_mmio)(struct kvm_vcpu *, struct kvm_run *,
+  struct kvm_exit_mmio *);
+   bool(*queue_sgi)(struct kvm_vcpu *vcpu, int irq);
+   void(*unqueue_sgi)(struct kvm_vcpu *vcpu, int irq, int source);
+   int (*vgic_init)(struct kvm *kvm, const struct vgic_params *params);
 };
 
 struct vgic_dist {
@@ -131,6 +140,9 @@ struct vgic_dist {
boolin_kernel;
boolready;
 
+   /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+   u32 vgic_model;
+
int nr_cpus;
int nr_irqs;
 
@@ -168,6 +180,8 @@ struct vgic_dist {
 
/* Bitmap indicating which CPU has something pending */
unsigned long   irq_pending_on_cpu;
+
+   struct vgic_vm_ops  vm_ops;
 #endif
 };
 
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 01124ef..90947c6 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -161,8 +161,6 @@ static void vgic_v2_enable(struct kvm_vcpu *vcpu)
 }
 
 static const struct vgic_ops vgic_v2_ops = {
-   .get_lr = vgic_v2_get_lr,
-   .set_lr = vgic_v2_set_lr,
.sync_lr_elrsr  = vgic_v2_sync_lr_elrsr,
.get_elrsr  = vgic_v2_get_elrsr,
.get_eisr   = vgic_v2_get_eisr,
@@ -176,6 +174,20 @@ static const struct vgic_ops vgic_v2_ops = {
 
 static struct vgic_params vgic_v2_params;
 
+static bool vgic_v2_init_emul(struct kvm *kvm, int type)
+{
+   struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   vm_ops-get_lr = vgic_v2_get_lr;
+   vm_ops-set_lr = vgic_v2_set_lr;
+   return true;
+   }
+
+   return false;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:  pointer to the DT node
@@ -214,6 +226,7 @@ int vgic_v2_probe(struct device_node *vgic_node,
ret = -ENOMEM;
goto out;
}
+   vgic-init_emul = vgic_v2_init_emul;
 
vgic-nr_lr = readl_relaxed(vgic-vctrl_base + GICH_VTR);
vgic-nr_lr = (vgic-nr_lr  0x3f) + 1;
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 1c2c8ee..a38339e 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -157,8 +157,6 @@ static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 }
 
 static const struct vgic_ops vgic_v3_ops = {
-   .get_lr = vgic_v3_get_lr,
-   .set_lr = vgic_v3_set_lr,
.sync_lr_elrsr  = vgic_v3_sync_lr_elrsr,
.get_elrsr  = vgic_v3_get_elrsr,
.get_eisr   = vgic_v3_get_eisr,
@@ -170,6 +168,19 @@ static const struct vgic_ops vgic_v3_ops = {
.enable = vgic_v3_enable,
 };
 
+static bool vgic_v3_init_emul_compat(struct kvm *kvm, int type)
+{
+   struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   vm_ops-get_lr = vgic_v3_get_lr

[PATCH v2 13/15] arm/arm64: KVM: add SGI system register trapping

2014-08-21 Thread Andre Przywara
While the injection of a (virtual) inter-processor interrupt (SGI)
on a GICv2 works by writing to a MMIO register, GICv3 uses system
registers to trigger them.
Trap the appropriate registers both on ARM and ARM64 machines and
call the SGI handler function in the vGICv3 emulation code.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/kvm/coproc.c   |   19 +++
 arch/arm64/kvm/sys_regs.c   |   26 ++
 virt/kvm/arm/vgic-v3-emul.c |2 +-
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 37a0fe1..1cd049f 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -230,6 +230,22 @@ done:
return true;
 }
 
+static bool access_gic_sgi(struct kvm_vcpu *vcpu,
+  const struct coproc_params *p,
+  const struct coproc_reg *r)
+{
+   u64 val;
+
+   if (!p-is_write)
+   return read_from_write_only(vcpu, p);
+
+   val = *vcpu_reg(vcpu, p-Rt1);
+   val |= (u64)*vcpu_reg(vcpu, p-Rt2)  32;
+   vgic_v3_dispatch_sgi(vcpu, val);
+
+   return true;
+}
+
 /*
  * Generic accessor for VM registers. Only called as long as HCR_TVM
  * is set.
@@ -401,6 +417,9 @@ static const struct coproc_reg cp15_regs[] = {
{ CRn(10), CRm( 3), Op1( 0), Op2( 1), is32,
access_vm_reg, reset_unknown, c10_AMAIR1},
 
+   /* ICC_SGI1R */
+   { CRm64(12), Op1( 0), is64, access_gic_sgi},
+
/* VBAR: swapped by interrupt.S. */
{ CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
NULL, reset_val, c12_VBAR, 0x },
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index a79538a..befbcfd 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -165,6 +165,27 @@ static bool access_sctlr(struct kvm_vcpu *vcpu,
return true;
 }
 
+/*
+ * Trapping on the GICv3 SGI system register.
+ * Forward the request to the VGIC emulation.
+ * The cp15_64 code makes sure this automatically works
+ * for both AArch64 and AArch32 accesses.
+ */
+static bool access_gic_sgi(struct kvm_vcpu *vcpu,
+  const struct sys_reg_params *p,
+  const struct sys_reg_desc *r)
+{
+   u64 val;
+
+   if (!p-is_write)
+   return read_from_write_only(vcpu, p);
+
+   val = *vcpu_reg(vcpu, p-Rt);
+   vgic_v3_dispatch_sgi(vcpu, val);
+
+   return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
const struct sys_reg_params *p,
const struct sys_reg_desc *r)
@@ -431,6 +452,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* VBAR_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b), Op2(0b000),
  NULL, reset_val, VBAR_EL1, 0 },
+   /* ICC_SGI1R_EL1 */
+   { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1011), Op2(0b101),
+ access_gic_sgi },
/* CONTEXTIDR_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b), Op2(0b001),
  access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
@@ -659,6 +683,8 @@ static const struct sys_reg_desc cp14_64_regs[] = {
  * register).
  */
 static const struct sys_reg_desc cp15_regs[] = {
+   { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
+
{ Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_sctlr, NULL, c1_SCTLR },
{ Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
{ Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
diff --git a/virt/kvm/arm/vgic-v3-emul.c b/virt/kvm/arm/vgic-v3-emul.c
index 82ca1b5..ac5c5ee 100644
--- a/virt/kvm/arm/vgic-v3-emul.c
+++ b/virt/kvm/arm/vgic-v3-emul.c
@@ -802,7 +802,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
 */
spin_lock(dist-lock);
kvm_for_each_vcpu(c, c_vcpu, kvm) {
-   if (target_cpus == 0)
+   if (!mode  target_cpus == 0)
break;
if (mode  c == vcpu_id)   /* not to myself */
continue;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 11/15] arm/arm64: KVM: add opaque private pointer to MMIO accessors

2014-08-21 Thread Andre Przywara
For a GICv2 there is always only one (v)CPU involved: the one that
does the access. On a GICv3 the access to a CPU redistributor is
memory-mapped, but not banked, so the (v)CPU affected is determined by
looking at the MMIO address region being accessed.
To allow passing the affected CPU into the accessors, extend them to
take an opaque private pointer parameter.
For the current GICv2 emulation we ignore it and simply pass NULL
on the call.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic-v2-emul.c |   41 -
 virt/kvm/arm/vgic.c |   15 ---
 virt/kvm/arm/vgic.h |7 ---
 3 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/virt/kvm/arm/vgic-v2-emul.c b/virt/kvm/arm/vgic-v2-emul.c
index a6bfd75..a913060 100644
--- a/virt/kvm/arm/vgic-v2-emul.c
+++ b/virt/kvm/arm/vgic-v2-emul.c
@@ -41,7 +41,8 @@ static u8 *vgic_get_sgi_sources(struct vgic_dist *dist, int 
vcpu_id, int sgi)
 }
 
 static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
-struct kvm_exit_mmio *mmio, phys_addr_t offset)
+struct kvm_exit_mmio *mmio, phys_addr_t offset,
+void *private)
 {
u32 reg;
u32 word_offset = offset  3;
@@ -77,7 +78,7 @@ static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
 
 static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
   struct kvm_exit_mmio *mmio,
-  phys_addr_t offset)
+  phys_addr_t offset, void *private)
 {
return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
  vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
@@ -85,7 +86,7 @@ static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
 
 static bool handle_mmio_clear_enable_reg(struct kvm_vcpu *vcpu,
 struct kvm_exit_mmio *mmio,
-phys_addr_t offset)
+phys_addr_t offset, void *private)
 {
return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
  vcpu-vcpu_id, ACCESS_WRITE_CLEARBIT);
@@ -93,7 +94,7 @@ static bool handle_mmio_clear_enable_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio,
-   phys_addr_t offset)
+   phys_addr_t offset, void *private)
 {
return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
   vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
@@ -101,7 +102,7 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
  struct kvm_exit_mmio *mmio,
- phys_addr_t offset)
+ phys_addr_t offset, void *private)
 {
return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
   vcpu-vcpu_id, ACCESS_WRITE_CLEARBIT);
@@ -109,7 +110,7 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_priority_reg(struct kvm_vcpu *vcpu,
 struct kvm_exit_mmio *mmio,
-phys_addr_t offset)
+phys_addr_t offset, void *private)
 {
u32 *reg = vgic_bytemap_get_reg(vcpu-kvm-arch.vgic.irq_priority,
vcpu-vcpu_id, offset);
@@ -168,7 +169,7 @@ static void vgic_set_target_reg(struct kvm *kvm, u32 val, 
int irq)
 
 static bool handle_mmio_target_reg(struct kvm_vcpu *vcpu,
   struct kvm_exit_mmio *mmio,
-  phys_addr_t offset)
+  phys_addr_t offset, void *private)
 {
u32 reg;
 
@@ -198,7 +199,8 @@ static bool handle_mmio_target_reg(struct kvm_vcpu *vcpu,
 }
 
 static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
-   struct kvm_exit_mmio *mmio, phys_addr_t offset)
+   struct kvm_exit_mmio *mmio, phys_addr_t offset,
+   void *private)
 {
u32 *reg;
 
@@ -209,7 +211,8 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
 }
 
 static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
-   struct kvm_exit_mmio *mmio, phys_addr_t offset)
+   struct kvm_exit_mmio *mmio, phys_addr_t offset,
+   void *private)
 {
u32 reg;
 
@@ -285,7 +288,7 @@ static bool write_set_clear_sgi_pend_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_sgi_set(struct kvm_vcpu *vcpu

[PATCH v2 02/15] arm/arm64: KVM: pass down user space provided GIC type into vGIC code

2014-08-21 Thread Andre Przywara
With the introduction of a second emulated GIC model we need to let
userspace specify the GIC model to use for each VM. Pass the
userspace provided value down into the vGIC code to differentiate
later.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/kvm/arm.c |2 +-
 include/kvm/arm_vgic.h |4 ++--
 virt/kvm/arm/vgic.c|4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index addb990..157e1b6 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -767,7 +767,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
switch (ioctl) {
case KVM_CREATE_IRQCHIP: {
if (vgic_present)
-   return kvm_vgic_create(kvm);
+   return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
else
return -ENXIO;
}
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f5788cf..4feac9a 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -231,7 +231,7 @@ struct kvm_exit_mmio;
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 int kvm_vgic_hyp_init(void);
 int kvm_vgic_init(struct kvm *kvm);
-int kvm_vgic_create(struct kvm *kvm);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
@@ -282,7 +282,7 @@ static inline int kvm_vgic_init(struct kvm *kvm)
return 0;
 }
 
-static inline int kvm_vgic_create(struct kvm *kvm)
+static inline int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index b3e5ee2..bba8692 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1864,7 +1864,7 @@ out:
return ret;
 }
 
-int kvm_vgic_create(struct kvm *kvm)
+int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
int i, vcpu_lock_idx = -1, ret = 0;
struct kvm_vcpu *vcpu;
@@ -2320,7 +2320,7 @@ static void vgic_destroy(struct kvm_device *dev)
 
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
-   return kvm_vgic_create(dev-kvm);
+   return kvm_vgic_create(dev-kvm, type);
 }
 
 struct kvm_device_ops kvm_arm_vgic_v2_ops = {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 00/15] KVM GICv3 emulation

2014-08-21 Thread Andre Przywara
This is an updated version of the GICv3 guest emulation series.
Compared to v1[1] it has been rebased on v3.17-rc1 (with quite some
conflict resolutions done by MarcZ) and contains minor fixes
(partially triggered by comments on the list, partially due to code
review caused by the rebase). Also there is a new patch (09/15) with
some refactoring to make the big split patch (10/15) smaller.
This big patch contains now an elaborate commit message to detail
the code move, as the diff isn't always obvious here. This part
should be considered for removal from the patch on committing it.

A git repo hosting all these patches lives in the kvm-gicv3/v2 branch
of: http://www.linux-arm.org/git?p=linux-ap.git
-

GICv3 is the ARM generic interrupt controller designed to overcome
some limits of the prevalent GICv2. Most notably it lifts the 8-CPU
limit. Though with recent patches from Marc there is support for
hosts to use a GICv3, the CPU limitation still applies to KVM guests,
since the current code emulates a GICv2 only.
Also, GICv2 backward compatibility being optional in GICv3, a number
of systems won't be able to run GICv2 guests.

This patch series provides code to emulate a GICv3 distributor and
redistributor for any KVM guest. It requires a GICv3 in the host to
work. With those patches one can run guests efficiently on any GICv3
host. It has the following features:
- Affinity routing (support for up to 255 VCPUs, more possible)
- System registers (as opposed to MMIO access)
- No ITS
- No priority support (as the GICv2 emulation)
- No save / restore support so far (will be added soon)

The first 11 patches actually refactor the current VGIC code to make
room for a different VGIC model to be dropped in with Patch 12/15.
The remaining patches connect the new model to the kernel backend and
the userland facing code.

The series goes on top of v3.17-rc1 and Marc's vgic-dyn series[2].
The necessary patches for kvmtool to enable the guest's GICv3 have
been posted here before [3], an updated version will follow as soon
as the kvmtools tree has been updated.

There was some testing on the fast model with some I/O and interrupt
affinity shuffling in a Linux guest with a varying number of VCPUs as
well as some testing on a Juno board (GICv2 only, to spot
regressions).

Please review and test.
I would be grateful for people to test for GICv2 regressions also
(so on a GICv2 host with current kvmtool/qemu), as there is quite
some refactoring on that front.

Much of the code was inspired by MarcZ, also kudos to him for doing
the rather painful rebase on top of v3.17-rc1.

Cheers,
Andre.

[1] https://lists.cs.columbia.edu/pipermail/kvmarm/2014-June/010060.html
[2] 
https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/vgic-dyn
[3] https://lists.cs.columbia.edu/pipermail/kvmarm/2014-June/010086.html

Changes v1 ... v2:
* rebase to v3.17-rc1, caused quite some changes to the init code
* new 9/15 patch to make 10/15 smaller
* fix wrongly ordered cp15 register trap entry (MarcZ)
* fix SGI broadcast (thanks to wanghaibin for spotting)
* fix broken bailout path in kvm_vgic_create (wanghaibin)
* check return value of init_emulation_ops() (wanghaibin)
* fix return value check in vgic_[sg]et_attr()
* add header inclusion guards
* remove double definition of VCPU_NOT_ALLOCATED
* some code move-around
* whitespace fixes


Andre Przywara (15):
  arm/arm64: KVM: rework MPIDR assignment and add accessors
  arm/arm64: KVM: pass down user space provided GIC type into vGIC code
  arm/arm64: KVM: refactor vgic_handle_mmio() function
  arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones
  arm/arm64: KVM: introduce per-VM ops
  arm/arm64: KVM: make the maximum number of vCPUs a per-VM value
  arm/arm64: KVM: make the value of ICC_SRE_EL1 a per-VM variable
  arm/arm64: KVM: refactor MMIO accessors
  arm/arm64: KVM: refactor/wrap vgic_set/get_attr()
  arm/arm64: KVM: split GICv2 specific emulation code from vgic.c
  arm/arm64: KVM: add opaque private pointer to MMIO accessors
  arm/arm64: KVM: add virtual GICv3 distributor emulation
  arm/arm64: KVM: add SGI system register trapping
  arm/arm64: KVM: enable kernel side of GICv3 emulation
  arm/arm64: KVM: allow userland to request a virtual GICv3

 arch/arm/include/asm/kvm_emulate.h   |2 +-
 arch/arm/include/asm/kvm_host.h  |3 +
 arch/arm/kvm/Makefile|1 +
 arch/arm/kvm/arm.c   |   23 +-
 arch/arm/kvm/coproc.c|   19 +
 arch/arm/kvm/psci.c  |   15 +-
 arch/arm64/include/asm/kvm_emulate.h |3 +-
 arch/arm64/include/asm/kvm_host.h|5 +
 arch/arm64/include/uapi/asm/kvm.h|7 +
 arch/arm64/kernel/asm-offsets.c  |1 +
 arch/arm64/kvm/Makefile  |2 +
 arch/arm64/kvm/sys_regs.c|   37 +-
 arch/arm64/kvm/vgic-v3-switch.S  |   14 +-
 include/kvm/arm_vgic.h   |   38 +-
 include/linux/irqchip/arm-gic-v3.h   |   26

[PATCH v2 03/15] arm/arm64: KVM: refactor vgic_handle_mmio() function

2014-08-21 Thread Andre Przywara
Currently we only need to deal with one MMIO region for the GIC
emulation, but we soon need to extend this. Refactor the existing
code to allow easier addition of different ranges without code
duplication.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   72 ---
 1 file changed, 51 insertions(+), 21 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index bba8692..3b6f78d 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -925,37 +925,28 @@ static bool vgic_validate_access(const struct vgic_dist 
*dist,
return true;
 }
 
-/**
- * vgic_handle_mmio - handle an in-kernel MMIO access
+/*
+ * vgic_handle_mmio_range - handle an in-kernel MMIO access
  * @vcpu:  pointer to the vcpu performing the access
  * @run:   pointer to the kvm_run structure
  * @mmio:  pointer to the data describing the access
+ * @ranges:pointer to the register defining structure
+ * @mmio_base: base address for this mapping
  *
- * returns true if the MMIO access has been performed in kernel space,
- * and false if it needs to be emulated in user space.
+ * returns true if the MMIO access could be performed
  */
-bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
- struct kvm_exit_mmio *mmio)
+static bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
+   struct kvm_exit_mmio *mmio,
+   const struct mmio_range *ranges,
+   unsigned long mmio_base)
 {
const struct mmio_range *range;
struct vgic_dist *dist = vcpu-kvm-arch.vgic;
-   unsigned long base = dist-vgic_dist_base;
bool updated_state;
unsigned long offset;
 
-   if (!irqchip_in_kernel(vcpu-kvm) ||
-   mmio-phys_addr  base ||
-   (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;
-   }
-
-   offset = mmio-phys_addr - base;
-   range = find_matching_range(vgic_dist_ranges, mmio, offset);
+   offset = mmio-phys_addr - mmio_base;
+   range = find_matching_range(ranges, mmio, offset);
if (unlikely(!range || !range-handle_mmio)) {
pr_warn(Unhandled access %d %08llx %d\n,
mmio-is_write, mmio-phys_addr, mmio-len);
@@ -963,7 +954,7 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run 
*run,
}
 
spin_lock(vcpu-kvm-arch.vgic.lock);
-   offset = mmio-phys_addr - range-base - base;
+   offset -= range-base;
if (vgic_validate_access(dist, range, offset)) {
updated_state = range-handle_mmio(vcpu, mmio, offset);
} else {
@@ -981,6 +972,45 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct 
kvm_run *run,
return true;
 }
 
+#define IS_IN_RANGE(addr, alen, base, len) \
+   (((addr) = (base))  (((addr) + (alen))  ((base) + (len
+
+static bool vgic_v2_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+   struct kvm_exit_mmio *mmio)
+{
+   unsigned long base = vcpu-kvm-arch.vgic.vgic_dist_base;
+
+   if (!IS_IN_RANGE(mmio-phys_addr, mmio-len, base,
+KVM_VGIC_V2_DIST_SIZE))
+   return false;
+
+   /* GICv2 does not support accesses wider than 32 bits */
+   if (mmio-len  4) {
+   kvm_inject_dabt(vcpu, mmio-phys_addr);
+   return true;
+   }
+
+   return vgic_handle_mmio_range(vcpu, run, mmio, vgic_dist_ranges, base);
+}
+
+/**
+ * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
+ * @vcpu:  pointer to the vcpu performing the access
+ * @run:   pointer to the kvm_run structure
+ * @mmio:  pointer to the data describing the access
+ *
+ * returns true if the MMIO access has been performed in kernel space,
+ * and false if it needs to be emulated in user space.
+ */
+bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+ struct kvm_exit_mmio *mmio)
+{
+   if (!irqchip_in_kernel(vcpu-kvm))
+   return false;
+
+   return vgic_v2_handle_mmio(vcpu, run, mmio);
+}
+
 static u8 *vgic_get_sgi_sources(struct vgic_dist *dist, int vcpu_id, int sgi)
 {
return dist-irq_sgi_sources + vcpu_id * VGIC_NR_SGIS + sgi;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 09/15] arm/arm64: KVM: refactor/wrap vgic_set/get_attr()

2014-08-21 Thread Andre Przywara
vgic_set_attr() and vgic_get_attr() contain both code specific for
the emulated GIC as well as code for the userland facing, generic
part of the GIC.
Split the guest GIC facing code of from the generic part to allow
easier splitting later.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   79 +++
 1 file changed, 54 insertions(+), 25 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index e8f92b2..3386557 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -2301,7 +2301,8 @@ out:
return ret;
 }
 
-static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+static int vgic_set_common_attr(struct kvm_device *dev,
+   struct kvm_device_attr *attr)
 {
int r;
 
@@ -2317,17 +2318,6 @@ static int vgic_set_attr(struct kvm_device *dev, struct 
kvm_device_attr *attr)
r = kvm_vgic_addr(dev-kvm, type, addr, true);
return (r == -ENODEV) ? -ENXIO : r;
}
-
-   case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
-   case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
-   u32 __user *uaddr = (u32 __user *)(long)attr-addr;
-   u32 reg;
-
-   if (get_user(reg, uaddr))
-   return -EFAULT;
-
-   return vgic_attr_regs_access(dev, attr, reg, true);
-   }
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
u32 __user *uaddr = (u32 __user *)(long)attr-addr;
u32 val;
@@ -2356,7 +2346,33 @@ static int vgic_set_attr(struct kvm_device *dev, struct 
kvm_device_attr *attr)
return -ENXIO;
 }
 
-static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+   int ret;
+
+   ret = vgic_set_common_attr(dev, attr);
+   if (ret != -ENXIO)
+   return ret;
+
+   switch (attr-group) {
+   case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+   case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+   u32 __user *uaddr = (u32 __user *)(long)attr-addr;
+   u32 reg;
+
+   if (get_user(reg, uaddr))
+   return -EFAULT;
+
+   return vgic_attr_regs_access(dev, attr, reg, true);
+   }
+
+   }
+
+   return -ENXIO;
+}
+
+static int vgic_get_common_attr(struct kvm_device *dev,
+   struct kvm_device_attr *attr)
 {
int r = -ENXIO;
 
@@ -2374,18 +2390,6 @@ static int vgic_get_attr(struct kvm_device *dev, struct 
kvm_device_attr *attr)
return -EFAULT;
break;
}
-
-   case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
-   case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
-   u32 __user *uaddr = (u32 __user *)(long)attr-addr;
-   u32 reg = 0;
-
-   r = vgic_attr_regs_access(dev, attr, reg, false);
-   if (r)
-   return r;
-   r = put_user(reg, uaddr);
-   break;
-   }
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
u32 __user *uaddr = (u32 __user *)(long)attr-addr;
r = put_user(dev-kvm-arch.vgic.nr_irqs, uaddr);
@@ -2403,6 +2407,31 @@ static int vgic_get_attr(struct kvm_device *dev, struct 
kvm_device_attr *attr)
return r;
 }
 
+static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+   int ret;
+
+   ret = vgic_get_common_attr(dev, attr);
+   if (ret != -ENXIO)
+   return ret;
+
+   switch (attr-group) {
+   case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+   case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+   u32 __user *uaddr = (u32 __user *)(long)attr-addr;
+   u32 reg = 0;
+
+   ret = vgic_attr_regs_access(dev, attr, reg, false);
+   if (ret)
+   return ret;
+   return put_user(reg, uaddr);
+   }
+
+   }
+
+   return -ENXIO;
+}
+
 static int vgic_has_attr_regs(const struct mmio_range *ranges,
  phys_addr_t offset)
 {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/14] KVM GICv3 emulation

2014-06-20 Thread Andre Przywara
On 20/06/14 02:39, Chalamarla, Tirumalesh wrote:

Hi Tirumalesh,

  Is there a public repo where we can get this patches from easily.

Indeed, many thanks to Marc who hosts now my patches on his kernel.org
repo. Simply checkout the gicv3/kvm-guest branch from
git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
to get all of GICv3 host, vgic-dyn and the GICv3 guest emualation stuff
at once.

Regards,
Andre.

 
 From: kvmarm-boun...@lists.cs.columbia.edu 
 kvmarm-boun...@lists.cs.columbia.edu on behalf of Andre Przywara 
 andre.przyw...@arm.com
 Sent: Thursday, June 19, 2014 3:15 PM
 To: linux-arm-ker...@lists.infradead.org; kvm...@lists.cs.columbia.edu; 
 kvm@vger.kernel.org
 Cc: christoffer.d...@linaro.org
 Subject: [PATCH 00/14] KVM GICv3 emulation

 GICv3 is the ARM generic interrupt controller designed to overcome
 some limits of the prevalent GICv2. Most notably it lifts the 8-CPU
 limit. Though with recent patches from Marc there is support for
 hosts to use a GICv3, the CPU limitation still applies to KVM guests,
 since the current code emulates a GICv2 only.
 Also, GICv2 backward compatibility being optional in GICv3, a number
 of systems won't be able to run GICv2 guests.

 This patch series provides code to emulate a GICv3 distributor and
 redistributor for any KVM guest. It requires a GICv3 in the host to
 work. With those patches one can run guests efficiently on any GICv3
 host. It has the following features:
 - Affinity routing (support for up to 255 VCPUs, more possible)
 - System registers (as opposed to MMIO access)
 - No ITS
 - No priority support (as the GICv2 emulation)
 - No save / restore support so far (will be added soon)

 The first 10 patches actually refactor the current VGIC code to make
 room for a different VGIC model to be dropped in with Patch 11/14.
 The remaining patches connect the new model to the kernel backend and
 the userland facing code.

 The series goes on top of both Marc's GICv3 host support series as
 well as his vgic-dyn patches.
 The necessary patches for kvmtool to enable the guest's GICv3 will be
 posted here as well.
 There was some testing on the fast model with some I/O and interrupt
 affinity shuffling in a Linux guest with a varying number of VCPUs.

 Please review and test.
 I would be grateful for people to test for GICv2 regressions also
 (so on a GICv2 host with current kvmtool/qemu), as there is quite
 some refactoring on that front.

 Much of the code was inspired by Marc, so send all praises to him
 (while I take the blame).

 Cheers,
 Andre.

 Andre Przywara (14):
   arm/arm64: KVM: rework MPIDR assignment and add accessors
   arm/arm64: KVM: pass down user space provided GIC type into vGIC code
   arm/arm64: KVM: refactor vgic_handle_mmio() function
   arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones
   arm/arm64: KVM: introduce per-VM ops
   arm/arm64: KVM: make the maximum number of vCPUs a per-VM value
   arm/arm64: KVM: make the value of ICC_SRE_EL1 a per-VM variable
   arm/arm64: KVM: refactor MMIO accessors
   arm/arm64: KVM: split GICv2 specific emulation code from vgic.c
   arm/arm64: KVM: add opaque private pointer to MMIO accessors
   arm/arm64: KVM: add virtual GICv3 distributor emulation
   arm/arm64: KVM: add SGI system register trapping
   arm/arm64: KVM: enable kernel side of GICv3 emulation
   arm/arm64: KVM: allow userland to request a virtual GICv3

  arch/arm/include/asm/kvm_emulate.h   |2 +-
  arch/arm/include/asm/kvm_host.h  |3 +
  arch/arm/kvm/Makefile|1 +
  arch/arm/kvm/arm.c   |   23 +-
  arch/arm/kvm/coproc.c|   19 +
  arch/arm/kvm/psci.c  |   15 +-
  arch/arm64/include/asm/kvm_emulate.h |3 +-
  arch/arm64/include/asm/kvm_host.h|5 +
  arch/arm64/include/uapi/asm/kvm.h|7 +
  arch/arm64/kernel/asm-offsets.c  |1 +
  arch/arm64/kvm/Makefile  |2 +
  arch/arm64/kvm/sys_regs.c|   37 +-
  arch/arm64/kvm/vgic-v3-switch.S  |   14 +-
  include/kvm/arm_vgic.h   |   38 +-
  include/linux/irqchip/arm-gic-v3.h   |   26 +
  include/linux/kvm_host.h |1 +
  include/uapi/linux/kvm.h |1 +
  virt/kvm/arm/vgic-v2-emul.c  |  802 +++
  virt/kvm/arm/vgic-v2.c   |   22 +-
  virt/kvm/arm/vgic-v3-emul.c  |  898 ++
  virt/kvm/arm/vgic-v3.c   |  157 +-
  virt/kvm/arm/vgic.c  | 1017 
 +++---
  virt/kvm/arm/vgic.h  |  117 
  virt/kvm/kvm_main.c  |3 +
  24 files changed, 2346 insertions(+), 868 deletions(-)
  create mode 100644 virt/kvm/arm/vgic-v2-emul.c
  create mode 100644 virt/kvm/arm/vgic-v3-emul.c
  create mode 100644 virt/kvm/arm/vgic.h

 --
 1.7.9.5

 ___
 kvmarm mailing

Re: [PATCH 04/14] arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones

2014-06-20 Thread Andre Przywara

On 19/06/14 22:15, Chalamarla, Tirumalesh wrote:


 -Original Message-
 From: kvmarm-boun...@lists.cs.columbia.edu 
 [mailto:kvmarm-boun...@lists.cs.columbia.edu] On Behalf Of Andre Przywara
 Sent: Thursday, June 19, 2014 2:46 AM
 To: linux-arm-ker...@lists.infradead.org; kvm...@lists.cs.columbia.edu; 
 kvm@vger.kernel.org
 Cc: christoffer.d...@linaro.org
 Subject: [PATCH 04/14] arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 
 bit ones

 Some GICv3 registers can and will be accessed as 64 bit registers.
 Currently the register handling code can only deal with 32 bit accesses, so 
 we do two consecutive calls to cover this.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  virt/kvm/arm/vgic.c |   48 +---
  1 file changed, 45 insertions(+), 3 deletions(-)

 diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 4c6b212..b3cf4c7 
 100644
 --- a/virt/kvm/arm/vgic.c
 +++ b/virt/kvm/arm/vgic.c
 @@ -906,6 +906,48 @@ static bool vgic_validate_access(const struct vgic_dist 
 *dist,  }

  /*
 + * Call the respective handler function for the given range.
 + * We split up any 64 bit accesses into two consecutive 32 bit
 + * handler calls and merge the result afterwards.
 + */
 +static bool call_range_handler(struct kvm_vcpu *vcpu,
 +struct kvm_exit_mmio *mmio,
 +unsigned long offset,
 +const struct mmio_range *range) {
 + u32 *data32 = (void *)mmio-data;
 + struct kvm_exit_mmio mmio32;
 + bool ret;
 +
 + if (likely(mmio-len = 4))
 + return range-handle_mmio(vcpu, mmio, offset);
 +
 + /*
 +  * We assume that any access greater than 4 bytes is actually
 +  * 8 bytes long, caused by a 64-bit access
 +  */
 +
 + mmio32.len = 4;
 + mmio32.is_write = mmio-is_write;
 +
 + mmio32.phys_addr = mmio-phys_addr + 4;
 + if (mmio-is_write)
 + *(u32 *)mmio32.data = data32[1];
 + ret = range-handle_mmio(vcpu, mmio32, offset + 4);
 + if (!mmio-is_write)
 + data32[1] = *(u32 *)mmio32.data;
 +
 + mmio32.phys_addr = mmio-phys_addr;
 + if (mmio-is_write)
 + *(u32 *)mmio32.data = data32[0];
 + ret |= range-handle_mmio(vcpu, mmio32, offset);
 + if (!mmio-is_write)
 + data32[0] = *(u32 *)mmio32.data;
 +
 + return ret;
 +}

 Any reason to use two 32 bits instead of one 64 bit. AArch32 on ARMv8 may be.

For the registers we care about right now we get along with this split.
And it seems to be less intrusive.
I have a patch to support native 64-bit accesses, but it needs some more
work. If there is high demand for it, I can post it (but Marc didn't
like the first version so much ;-) )

Regards,
Andre.


 +
 +/*
   * vgic_handle_mmio_range - handle an in-kernel MMIO access
   * @vcpu:pointer to the vcpu performing the access
   * @run: pointer to the kvm_run structure
 @@ -936,10 +978,10 @@ static bool vgic_handle_mmio_range(struct kvm_vcpu 
 *vcpu, struct kvm_run *run,
   spin_lock(vcpu-kvm-arch.vgic.lock);
   offset -= range-base;
   if (vgic_validate_access(dist, range, offset)) {
 - updated_state = range-handle_mmio(vcpu, mmio, offset);
 + updated_state = call_range_handler(vcpu, mmio, offset, range);
   } else {
 - vgic_reg_access(mmio, NULL, offset,
 - ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
 + if (!mmio-is_write)
 + memset(mmio-data, 0, mmio-len);

  What is the use of this memset.

   updated_state = false;
   }
   spin_unlock(vcpu-kvm-arch.vgic.lock);
 --
 1.7.9.5

 ___
 kvmarm mailing list
 kvm...@lists.cs.columbia.edu
 https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


-- IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered 
in England  Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, 
Registered in England  Wales, Company No:  2548782

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 13/14] arm/arm64: KVM: enable kernel side of GICv3 emulation

2014-06-20 Thread Andre Przywara


On 19/06/14 22:43, Chalamarla, Tirumalesh wrote:


 -Original Message-
 From: kvmarm-boun...@lists.cs.columbia.edu 
 [mailto:kvmarm-boun...@lists.cs.columbia.edu] On Behalf Of Andre Przywara
 Sent: Thursday, June 19, 2014 2:46 AM
 To: linux-arm-ker...@lists.infradead.org; kvm...@lists.cs.columbia.edu; 
 kvm@vger.kernel.org
 Cc: christoffer.d...@linaro.org
 Subject: [PATCH 13/14] arm/arm64: KVM: enable kernel side of GICv3 emulation

 With all the necessary GICv3 emulation code in place, we can now connect the 
 code to the GICv3 backend in the kernel.
 The LR register handling is different depending on the emulated GIC model, so 
 provide different implementations for each.
 Also allow non-v2-compatible GICv3 implementations (which don't provide MMIO 
 regions for the virtual CPU interface in the DT), but restrict those hosts to 
 use GICv3 guests only.

 Signed-off-by: Andre Przywara andre.przyw...@arm.com
 ---
  virt/kvm/arm/vgic-v3.c |  138 
 ++--
  virt/kvm/arm/vgic.c|2 +
  2 files changed, 112 insertions(+), 28 deletions(-)

 diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index 
 7d9c85e..d26d12f 100644
 --- a/virt/kvm/arm/vgic-v3.c
 +++ b/virt/kvm/arm/vgic-v3.c
 @@ -34,6 +34,7 @@
  #define GICH_LR_VIRTUALID(0x3ffUL  0)
  #define GICH_LR_PHYSID_CPUID_SHIFT   (10)
  #define GICH_LR_PHYSID_CPUID (7UL  GICH_LR_PHYSID_CPUID_SHIFT)
 +#define ICH_LR_VIRTUALID_MASK(BIT_ULL(32) - 1)

  /*
   * LRs are stored in reverse order in memory. make sure we index them @@ 
 -43,7 +44,35 @@

  static u32 ich_vtr_el2;

 -static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 +static u64 sync_lr_val(u8 state)
 +{
 + u64 lr_val = 0;
 +
 + if (state  LR_STATE_PENDING)
 + lr_val |= ICH_LR_PENDING_BIT;
 + if (state  LR_STATE_ACTIVE)
 + lr_val |= ICH_LR_ACTIVE_BIT;
 + if (state  LR_EOI_INT)
 + lr_val |= ICH_LR_EOI;
 +
 + return lr_val;
 +}
 +
 +static u8 sync_lr_state(u64 lr_val)
 +{
 + u8 state = 0;
 +
 + if (lr_val  ICH_LR_PENDING_BIT)
 + state |= LR_STATE_PENDING;
 + if (lr_val  ICH_LR_ACTIVE_BIT)
 + state |= LR_STATE_ACTIVE;
 + if (lr_val  ICH_LR_EOI)
 + state |= LR_EOI_INT;
 +
 + return state;
 +}
 +
 +static struct vgic_lr vgic_v2_on_v3_get_lr(const struct kvm_vcpu *vcpu,
 +int lr)
  {
   struct vgic_lr lr_desc;
   u64 val = vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
 @@ -53,30 +82,53 @@ static struct vgic_lr vgic_v3_get_lr(const struct 
 kvm_vcpu *vcpu, int lr)
   lr_desc.source  = (val  GICH_LR_PHYSID_CPUID_SHIFT)  0x7;
   else
   lr_desc.source = 0;
 - lr_desc.state   = 0;
 + lr_desc.state   = sync_lr_state(val);

 - if (val  ICH_LR_PENDING_BIT)
 - lr_desc.state |= LR_STATE_PENDING;
 - if (val  ICH_LR_ACTIVE_BIT)
 - lr_desc.state |= LR_STATE_ACTIVE;
 - if (val  ICH_LR_EOI)
 - lr_desc.state |= LR_EOI_INT;
 + return lr_desc;
 +}
 +
 +static struct vgic_lr vgic_v3_on_v3_get_lr(const struct kvm_vcpu *vcpu,
 +int lr) {
 + struct vgic_lr lr_desc;
 + u64 val = vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
 +
 + lr_desc.irq = val  ICH_LR_VIRTUALID_MASK;
 + lr_desc.source  = 0;
 + lr_desc.state   = sync_lr_state(val);

   return lr_desc;
  }

 -static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
 -struct vgic_lr lr_desc)
 +static void vgic_v3_on_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
 +  struct vgic_lr lr_desc)
  {
 - u64 lr_val = (((u32)lr_desc.source  GICH_LR_PHYSID_CPUID_SHIFT) |
 -   lr_desc.irq);
 + u64 lr_val;

 - if (lr_desc.state  LR_STATE_PENDING)
 - lr_val |= ICH_LR_PENDING_BIT;
 - if (lr_desc.state  LR_STATE_ACTIVE)
 - lr_val |= ICH_LR_ACTIVE_BIT;
 - if (lr_desc.state  LR_EOI_INT)
 - lr_val |= ICH_LR_EOI;
 + lr_val = lr_desc.irq;
 +
 + /*
 +  * currently all guest IRQs are Group1, as Group0 would result
 +  * in a FIQ in the guest, which it wouldn't expect.
 +  * Eventually we want to make this configurable, so we may revisit
 +  * this in the future.
 +  */
 + lr_val |= ICH_LR_GROUP;
 +
 + lr_val |= sync_lr_val(lr_desc.state);
 +
 + vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val; }
 +
 +static void vgic_v2_on_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
 +  struct vgic_lr lr_desc)
 +{
 + u64 lr_val;
 +
 + lr_val = lr_desc.irq;
 +
 + lr_val |= (u32)lr_desc.source  GICH_LR_PHYSID_CPUID_SHIFT;
 +
 + lr_val |= sync_lr_val(lr_desc.state);

   vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val;  } @@ 
 -145,9 +197,8 @@ static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct 
 vgic_vmcr *vmcrp)

  static void

[PATCH 07/14] arm/arm64: KVM: make the value of ICC_SRE_EL1 a per-VM variable

2014-06-19 Thread Andre Przywara
ICC_SRE_EL1 is a system register allowing msr/mrs accesses to the
GIC CPU interface for EL1 (guests). Currently we force it to 0, but
for proper GICv3 support we have to allow guests to use it (depending
on their selected virtual GIC model).
So add ICC_SRE_EL1 to the list of saved/restored registers on a
world switch, but actually disallow a guest to change it by only
restoring a fixed, once-initialized value.
This value depends on the GIC model userland has chosen for a guest.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/kernel/asm-offsets.c |1 +
 arch/arm64/kvm/vgic-v3-switch.S |   14 +-
 include/kvm/arm_vgic.h  |1 +
 virt/kvm/arm/vgic-v3.c  |9 +++--
 4 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index e74654c..0f24b21 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -139,6 +139,7 @@ int main(void)
   DEFINE(VGIC_V2_CPU_ELRSR,offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
   DEFINE(VGIC_V2_CPU_APR,  offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
   DEFINE(VGIC_V2_CPU_LR,   offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
+  DEFINE(VGIC_V3_CPU_SRE,  offsetof(struct vgic_cpu, vgic_v3.vgic_sre));
   DEFINE(VGIC_V3_CPU_HCR,  offsetof(struct vgic_cpu, vgic_v3.vgic_hcr));
   DEFINE(VGIC_V3_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr));
   DEFINE(VGIC_V3_CPU_MISR, offsetof(struct vgic_cpu, vgic_v3.vgic_misr));
diff --git a/arch/arm64/kvm/vgic-v3-switch.S b/arch/arm64/kvm/vgic-v3-switch.S
index 4ede9d8..c0cfd16 100644
--- a/arch/arm64/kvm/vgic-v3-switch.S
+++ b/arch/arm64/kvm/vgic-v3-switch.S
@@ -148,17 +148,18 @@
  * x0: Register pointing to VCPU struct
  */
 .macro restore_vgic_v3_state
-   // Disable SRE_EL1 access. Necessary, otherwise
-   // ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens...
-   msr ICC_SRE_EL1, xzr
-   isb
-
// Compute the address of struct vgic_cpu
add x3, x0, #VCPU_VGIC_CPU
 
// Restore all interesting registers
ldr w4, [x3, #VGIC_V3_CPU_HCR]
ldr w5, [x3, #VGIC_V3_CPU_VMCR]
+   ldr w25, [x3, #VGIC_V3_CPU_SRE]
+
+   msr ICC_SRE_EL1, x25
+
+   // make sure SRE is valid before writing the other registers
+   isb
 
msr ICH_HCR_EL2, x4
msr ICH_VMCR_EL2, x5
@@ -243,9 +244,12 @@
dsb sy
 
// Prevent the guest from touching the GIC system registers
+   // if SRE isn't enabled for GICv3 emulation
+   cbnzx25, 1f
mrs x5, ICC_SRE_EL2
and x5, x5, #~ICC_SRE_EL2_ENABLE
msr ICC_SRE_EL2, x5
+1:
 .endm
 
 ENTRY(__save_vgic_v3_state)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 7e7c99e..8aa8482 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -199,6 +199,7 @@ struct vgic_v3_cpu_if {
 #ifdef CONFIG_ARM_GIC_V3
u32 vgic_hcr;
u32 vgic_vmcr;
+   u32 vgic_sre;   /* Restored only, change ignored */
u32 vgic_misr;  /* Saved only */
u32 vgic_eisr;  /* Saved only */
u32 vgic_elrsr; /* Saved only */
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 40d6817..7d9c85e 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -145,15 +145,20 @@ static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, 
struct vgic_vmcr *vmcrp)
 
 static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
+   struct vgic_v3_cpu_if *vgic_v3;
+
+   vgic_v3 = vcpu-arch.vgic_cpu.vgic_v3;
/*
 * By forcing VMCR to zero, the GIC will restore the binary
 * points to their reset values. Anything else resets to zero
 * anyway.
 */
-   vcpu-arch.vgic_cpu.vgic_v3.vgic_vmcr = 0;
+   vgic_v3-vgic_vmcr = 0;
+
+   vgic_v3-vgic_sre   = 0;
 
/* Get the show on the road... */
-   vcpu-arch.vgic_cpu.vgic_v3.vgic_hcr = ICH_HCR_EN;
+   vgic_v3-vgic_hcr = ICH_HCR_EN;
 }
 
 static const struct vgic_ops vgic_v3_ops = {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/14] arm/arm64: KVM: add SGI system register trapping

2014-06-19 Thread Andre Przywara
While the injection of a (virtual) inter-processor interrupt (SGI)
on a GICv2 works by writing to a MMIO register, GICv3 uses system
registers to trigger them.
Trap the appropriate registers both on ARM and ARM64 machines and
call the SGI handler function in the vGICv3 emulation code.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/kvm/coproc.c |   19 +++
 arch/arm64/kvm/sys_regs.c |   26 ++
 2 files changed, 45 insertions(+)

diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index c58a351..4adadb7 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -205,6 +205,22 @@ done:
return true;
 }
 
+static bool access_gic_sgi(struct kvm_vcpu *vcpu,
+  const struct coproc_params *p,
+  const struct coproc_reg *r)
+{
+   u64 val;
+
+   if (!p-is_write)
+   return read_from_write_only(vcpu, p);
+
+   val = *vcpu_reg(vcpu, p-Rt1);
+   val |= (u64)*vcpu_reg(vcpu, p-Rt2)  32;
+   vgic_v3_dispatch_sgi(vcpu, val);
+
+   return true;
+}
+
 /*
  * Generic accessor for VM registers. Only called as long as HCR_TVM
  * is set.
@@ -376,6 +392,9 @@ static const struct coproc_reg cp15_regs[] = {
{ CRn(10), CRm( 3), Op1( 0), Op2( 1), is32,
access_vm_reg, reset_unknown, c10_AMAIR1},
 
+   /* ICC_SGI1R */
+   { CRm64(12), Op1( 0), is64, access_gic_sgi},
+
/* VBAR: swapped by interrupt.S. */
{ CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
NULL, reset_val, c12_VBAR, 0x },
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index fa2273a..012f21a 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -164,6 +164,27 @@ static bool access_sctlr(struct kvm_vcpu *vcpu,
 }
 
 /*
+ * Trapping on the GICv3 SGI system register.
+ * Forward the request to the VGIC emulation.
+ * The cp15_64 code makes sure this automatically works
+ * for both AArch64 and AArch32 accesses.
+ */
+static bool access_gic_sgi(struct kvm_vcpu *vcpu,
+  const struct sys_reg_params *p,
+  const struct sys_reg_desc *r)
+{
+   u64 val;
+
+   if (!p-is_write)
+   return read_from_write_only(vcpu, p);
+
+   val = *vcpu_reg(vcpu, p-Rt);
+   vgic_v3_dispatch_sgi(vcpu, val);
+
+   return true;
+}
+
+/*
  * We could trap ID_DFR0 and tell the guest we don't support performance
  * monitoring.  Unfortunately the patch to make the kernel check ID_DFR0 was
  * NAKed, so it will read the PMCR anyway.
@@ -282,6 +303,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
/* VBAR_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b), Op2(0b000),
  NULL, reset_val, VBAR_EL1, 0 },
+   /* ICC_SGI1R_EL1 */
+   { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1011), Op2(0b101),
+ access_gic_sgi },
/* CONTEXTIDR_EL1 */
{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b), Op2(0b001),
  access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
@@ -374,6 +398,8 @@ static const struct sys_reg_desc cp15_regs[] = {
{ Op1( 0), CRn( 6), CRm( 0), Op2( 0), access_vm_reg, NULL, c6_DFAR },
{ Op1( 0), CRn( 6), CRm( 0), Op2( 2), access_vm_reg, NULL, c6_IFAR },
 
+   { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
+
/*
 * DC{C,I,CI}SW operations:
 */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/14] arm/arm64: KVM: add virtual GICv3 distributor emulation

2014-06-19 Thread Andre Przywara
With everything separated and prepared, we implement a model of a
GICv3 distributor and redistributors by using the existing framework
to provide handler functions for each register group.
Currently we limit the emulation to a model enforcing a single
security state, with SRE==1 (forcing system register access) and
ARE==1 (allowing more than 8 VCPUs).
We share some of functions provided for GICv2 emulation, but take
the different ways of addressing (v)CPUs into account.
Save and restore is currently not implemented.

Similar to the split-off GICv2 specific code, the new emulation code
goes into a new file (vgic-v3-emul.c).

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/kvm/Makefile|1 +
 include/kvm/arm_vgic.h |   11 +-
 include/linux/irqchip/arm-gic-v3.h |   26 ++
 include/linux/kvm_host.h   |1 +
 include/uapi/linux/kvm.h   |1 +
 virt/kvm/arm/vgic-v3-emul.c|  895 
 virt/kvm/arm/vgic.c|   11 +-
 virt/kvm/arm/vgic.h|3 +
 virt/kvm/kvm_main.c|3 +
 9 files changed, 949 insertions(+), 3 deletions(-)
 create mode 100644 virt/kvm/arm/vgic-v3-emul.c

diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index f241db6..2fba3a5 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -21,6 +21,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o 
sys_regs_generic_v8.o
 
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3-emul.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 8aa8482..3b164ee 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -151,7 +151,11 @@ struct vgic_dist {
 
/* Distributor and vcpu interface mapping in the guest */
phys_addr_t vgic_dist_base;
-   phys_addr_t vgic_cpu_base;
+   /* GICv2 and GICv3 use different mapped register blocks */
+   union {
+   phys_addr_t vgic_cpu_base;
+   phys_addr_t vgic_redist_base;
+   };
 
/* Distributor enabled */
u32 enabled;
@@ -176,6 +180,10 @@ struct vgic_dist {
 
/* Target CPU for each IRQ */
u8  *irq_spi_cpu;
+
+   /* Target MPIDR for each IRQ (needed for GICv3 IROUTERn) only */
+   u32 *irq_spi_mpidr;
+
struct vgic_bitmap  *irq_spi_target;
 
/* Bitmap indicating which CPU has something pending */
@@ -253,6 +261,7 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
bool level);
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
 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);
diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index 9eac712..9f17e57 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -31,6 +31,7 @@
 #define GICD_SETSPI_SR 0x0050
 #define GICD_CLRSPI_SR 0x0058
 #define GICD_SEIR  0x0068
+#define GICD_IGROUPR   0x0080
 #define GICD_ISENABLER 0x0100
 #define GICD_ICENABLER 0x0180
 #define GICD_ISPENDR   0x0200
@@ -39,19 +40,38 @@
 #define GICD_ICACTIVER 0x0380
 #define GICD_IPRIORITYR0x0400
 #define GICD_ICFGR 0x0C00
+#define GICD_IGRPMODR  0x0D00
+#define GICD_NSACR 0x0E00
 #define GICD_IROUTER   0x6000
+#define GICD_IDREGS0xFFD0
 #define GICD_PIDR2 0xFFE8
 
+/*
+ * Non-ARE distributor registers, needed to provide the RES0
+ * semantics for KVM's emulated GICv3
+ */
+#define GICD_ITARGETSR 0x0800
+#define GICD_SGIR  0x0F00
+#define GICD_CPENDSGIR 0x0F10
+#define GICD_SPENDSGIR 0x0F20
+
+
 #define GICD_CTLR_RWP  (1U  31)
+#define GICD_CTLR_DS   (1U  6)
 #define GICD_CTLR_ARE_NS   (1U  4)
 #define GICD_CTLR_ENABLE_G1A   (1U  1)
 #define GICD_CTLR_ENABLE_G1(1U  0)
 
+#define GICD_TYPER_LPIS(1U  17)
+#define GICD_TYPER_MBIS(1U  16)
+
 #define GICD_IROUTER_SPI_MODE_ONE  (0U  31)
 #define GICD_IROUTER_SPI_MODE_ANY  (1U  31)
 
 #define

[PATCH 05/14] arm/arm64: KVM: introduce per-VM ops

2014-06-19 Thread Andre Przywara
Currently we only have one virtual GIC model supported, so all guests
use the same emulation code. With the addition of another model we
end up with different guests using potentially different vGIC models,
so we have to split up some functions to be per VM.
Introduce a vgic_vm_ops struct to hold function pointers for those
functions that are different and provide the necessary code to
initialize them.
This includes functions that depend on the emulated GIC model only
and functions that depend on the combination of host and guest GIC.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 include/kvm/arm_vgic.h |   18 +++-
 virt/kvm/arm/vgic-v2.c |   17 +++-
 virt/kvm/arm/vgic-v3.c |   16 ++-
 virt/kvm/arm/vgic.c|  109 +---
 4 files changed, 121 insertions(+), 39 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 4feac9a..7e7c99e 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -99,8 +99,6 @@ struct vgic_vmcr {
 };
 
 struct vgic_ops {
-   struct vgic_lr  (*get_lr)(const struct kvm_vcpu *, int);
-   void(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
void(*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
u64 (*get_elrsr)(const struct kvm_vcpu *vcpu);
u64 (*get_eisr)(const struct kvm_vcpu *vcpu);
@@ -123,6 +121,17 @@ struct vgic_params {
unsigned intmaint_irq;
/* Virtual control interface base address */
void __iomem*vctrl_base;
+   bool (*init_emul)(struct kvm *kvm, int type);
+};
+
+struct vgic_vm_ops {
+   struct vgic_lr  (*get_lr)(const struct kvm_vcpu *, int);
+   void(*set_lr)(struct kvm_vcpu *, int, struct vgic_lr);
+   bool(*handle_mmio)(struct kvm_vcpu *, struct kvm_run *,
+  struct kvm_exit_mmio *);
+   bool(*queue_sgi)(struct kvm_vcpu *vcpu, int irq);
+   void(*unqueue_sgi)(struct kvm_vcpu *vcpu, int irq, int source);
+   int (*vgic_init)(struct kvm *kvm, const struct vgic_params *params);
 };
 
 struct vgic_dist {
@@ -131,6 +140,9 @@ struct vgic_dist {
boolin_kernel;
boolready;
 
+   /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
+   u32 vgic_model;
+
int nr_cpus;
int nr_irqs;
 
@@ -168,6 +180,8 @@ struct vgic_dist {
 
/* Bitmap indicating which CPU has something pending */
unsigned long   irq_pending_on_cpu;
+
+   struct vgic_vm_ops  vm_ops;
 #endif
 };
 
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index a55a9a4..f2c214a 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -148,8 +148,6 @@ static void vgic_v2_enable(struct kvm_vcpu *vcpu)
 }
 
 static const struct vgic_ops vgic_v2_ops = {
-   .get_lr = vgic_v2_get_lr,
-   .set_lr = vgic_v2_set_lr,
.sync_lr_elrsr  = vgic_v2_sync_lr_elrsr,
.get_elrsr  = vgic_v2_get_elrsr,
.get_eisr   = vgic_v2_get_eisr,
@@ -163,6 +161,20 @@ static const struct vgic_ops vgic_v2_ops = {
 
 static struct vgic_params vgic_v2_params;
 
+static bool vgic_v2_init_emul(struct kvm *kvm, int type)
+{
+   struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   vm_ops-get_lr = vgic_v2_get_lr;
+   vm_ops-set_lr = vgic_v2_set_lr;
+   return true;
+   }
+
+   return false;
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:  pointer to the DT node
@@ -201,6 +213,7 @@ int vgic_v2_probe(struct device_node *vgic_node,
ret = -ENOMEM;
goto out;
}
+   vgic-init_emul = vgic_v2_init_emul;
 
vgic-nr_lr = readl_relaxed(vgic-vctrl_base + GICH_VTR);
vgic-nr_lr = (vgic-nr_lr  0x3f) + 1;
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index f01d446..f42961c 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -157,8 +157,6 @@ static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 }
 
 static const struct vgic_ops vgic_v3_ops = {
-   .get_lr = vgic_v3_get_lr,
-   .set_lr = vgic_v3_set_lr,
.sync_lr_elrsr  = vgic_v3_sync_lr_elrsr,
.get_elrsr  = vgic_v3_get_elrsr,
.get_eisr   = vgic_v3_get_eisr,
@@ -170,6 +168,19 @@ static const struct vgic_ops vgic_v3_ops = {
.enable = vgic_v3_enable,
 };
 
+static bool vgic_v3_init_emul_compat(struct kvm *kvm, int type)
+{
+   struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   vm_ops-get_lr = vgic_v3_get_lr

[PATCH 09/14] arm/arm64: KVM: split GICv2 specific emulation code from vgic.c

2014-06-19 Thread Andre Przywara
vgic.c is currently a mixture of generic vGIC emulation code and
functions specific to emulating a GICv2. To ease the addition of
GICv3, split off strictly v2 specific parts into a new file
vgic-v2-emul.c.
A new header file vgic.h is introduced to allow separation and later
sharing of functions.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/kvm/Makefile   |1 +
 arch/arm64/kvm/Makefile |1 +
 virt/kvm/arm/vgic-v2-emul.c |  795 
 virt/kvm/arm/vgic.c |  856 +++
 virt/kvm/arm/vgic.h |  113 ++
 5 files changed, 956 insertions(+), 810 deletions(-)
 create mode 100644 virt/kvm/arm/vgic-v2-emul.c
 create mode 100644 virt/kvm/arm/vgic.h

diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index f7057ed..443b8be 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -22,4 +22,5 @@ obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
 obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
 obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
+obj-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
 obj-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 32a0961..f241db6 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -20,6 +20,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o
 
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
+kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
 kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v3.o
diff --git a/virt/kvm/arm/vgic-v2-emul.c b/virt/kvm/arm/vgic-v2-emul.c
new file mode 100644
index 000..ba5f873
--- /dev/null
+++ b/virt/kvm/arm/vgic-v2-emul.c
@@ -0,0 +1,795 @@
+/*
+ * Contains GICv2 specific emulation code, was in vgic.c before.
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier marc.zyng...@arm.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/.
+ */
+
+#include linux/cpu.h
+#include linux/kvm.h
+#include linux/kvm_host.h
+#include linux/interrupt.h
+#include linux/io.h
+#include linux/uaccess.h
+
+#include linux/irqchip/arm-gic.h
+
+#include asm/kvm_emulate.h
+#include asm/kvm_arm.h
+#include asm/kvm_mmu.h
+
+#include vgic.h
+
+#define GICC_ARCH_VERSION_V20x2
+
+static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg);
+static u8 *vgic_get_sgi_sources(struct vgic_dist *dist, int vcpu_id, int sgi)
+{
+   return dist-irq_sgi_sources + vcpu_id * VGIC_NR_SGIS + sgi;
+}
+
+static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
+struct kvm_exit_mmio *mmio, phys_addr_t offset)
+{
+   u32 reg;
+   u32 word_offset = offset  3;
+
+   switch (offset  ~3) {
+   case 0: /* GICD_CTLR */
+   reg = vcpu-kvm-arch.vgic.enabled;
+   vgic_reg_access(mmio, reg, word_offset,
+   ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
+   if (mmio-is_write) {
+   vcpu-kvm-arch.vgic.enabled = reg  1;
+   vgic_update_state(vcpu-kvm);
+   return true;
+   }
+   break;
+
+   case 4: /* GICD_TYPER */
+   reg  = (atomic_read(vcpu-kvm-online_vcpus) - 1)  5;
+   reg |= (vcpu-kvm-arch.vgic.nr_irqs  5) - 1;
+   vgic_reg_access(mmio, reg, word_offset,
+   ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
+   break;
+
+   case 8: /* GICD_IIDR */
+   reg = (PRODUCT_ID_KVM  24) | (IMPLEMENTER_ARM  0);
+   vgic_reg_access(mmio, reg, word_offset,
+   ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
+   break;
+   }
+
+   return false;
+}
+
+static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
+  struct kvm_exit_mmio *mmio,
+  phys_addr_t offset)
+{
+   return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
+ vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
+}
+
+static bool

[PATCH 03/14] arm/arm64: KVM: refactor vgic_handle_mmio() function

2014-06-19 Thread Andre Przywara
Currently we only need to deal with one MMIO region for the GIC
emulation, but we soon need to extend this. Refactor the existing
code to allow easier addition of different ranges without code
duplication.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   72 ---
 1 file changed, 51 insertions(+), 21 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 8f1daf2..4c6b212 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -905,37 +905,28 @@ static bool vgic_validate_access(const struct vgic_dist 
*dist,
return true;
 }
 
-/**
- * vgic_handle_mmio - handle an in-kernel MMIO access
+/*
+ * vgic_handle_mmio_range - handle an in-kernel MMIO access
  * @vcpu:  pointer to the vcpu performing the access
  * @run:   pointer to the kvm_run structure
  * @mmio:  pointer to the data describing the access
+ * @ranges:pointer to the register defining structure
+ * @mmio_base: base address for this mapping
  *
- * returns true if the MMIO access has been performed in kernel space,
- * and false if it needs to be emulated in user space.
+ * returns true if the MMIO access could be performed
  */
-bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
- struct kvm_exit_mmio *mmio)
+static bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, struct kvm_run *run,
+   struct kvm_exit_mmio *mmio,
+   const struct mmio_range *ranges,
+   unsigned long mmio_base)
 {
const struct mmio_range *range;
struct vgic_dist *dist = vcpu-kvm-arch.vgic;
-   unsigned long base = dist-vgic_dist_base;
bool updated_state;
unsigned long offset;
 
-   if (!irqchip_in_kernel(vcpu-kvm) ||
-   mmio-phys_addr  base ||
-   (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;
-   }
-
-   offset = mmio-phys_addr - base;
-   range = find_matching_range(vgic_dist_ranges, mmio, offset);
+   offset = mmio-phys_addr - mmio_base;
+   range = find_matching_range(ranges, mmio, offset);
if (unlikely(!range || !range-handle_mmio)) {
pr_warn(Unhandled access %d %08llx %d\n,
mmio-is_write, mmio-phys_addr, mmio-len);
@@ -943,7 +934,7 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run 
*run,
}
 
spin_lock(vcpu-kvm-arch.vgic.lock);
-   offset = mmio-phys_addr - range-base - base;
+   offset -= range-base;
if (vgic_validate_access(dist, range, offset)) {
updated_state = range-handle_mmio(vcpu, mmio, offset);
} else {
@@ -961,6 +952,45 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct 
kvm_run *run,
return true;
 }
 
+#define IS_IN_RANGE(addr, alen, base, len) \
+   (((addr) = (base))  (((addr) + (alen))  ((base) + (len
+
+static bool vgic_v2_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+   struct kvm_exit_mmio *mmio)
+{
+   unsigned long base = vcpu-kvm-arch.vgic.vgic_dist_base;
+
+   if (!IS_IN_RANGE(mmio-phys_addr, mmio-len, base,
+KVM_VGIC_V2_DIST_SIZE))
+   return false;
+
+   /* GICv2 does not support accesses wider than 32 bits */
+   if (mmio-len  4) {
+   kvm_inject_dabt(vcpu, mmio-phys_addr);
+   return true;
+   }
+
+   return vgic_handle_mmio_range(vcpu, run, mmio, vgic_dist_ranges, base);
+}
+
+/**
+ * vgic_handle_mmio - handle an in-kernel MMIO access for the GIC emulation
+ * @vcpu:  pointer to the vcpu performing the access
+ * @run:   pointer to the kvm_run structure
+ * @mmio:  pointer to the data describing the access
+ *
+ * returns true if the MMIO access has been performed in kernel space,
+ * and false if it needs to be emulated in user space.
+ */
+bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
+ struct kvm_exit_mmio *mmio)
+{
+   if (!irqchip_in_kernel(vcpu-kvm))
+   return false;
+
+   return vgic_v2_handle_mmio(vcpu, run, mmio);
+}
+
 static u8 *vgic_get_sgi_sources(struct vgic_dist *dist, int vcpu_id, int sgi)
 {
return dist-irq_sgi_sources + vcpu_id * VGIC_NR_SGIS + sgi;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/14] arm/arm64: KVM: pass down user space provided GIC type into vGIC code

2014-06-19 Thread Andre Przywara
With the introduction of a second emulated GIC model we need to let
userspace specify the GIC model to use for each VM. Pass the
userspace provided value down into the vGIC code to differentiate
later.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/kvm/arm.c |2 +-
 include/kvm/arm_vgic.h |4 ++--
 virt/kvm/arm/vgic.c|4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9ffe962..fa37fa1 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -804,7 +804,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
switch (ioctl) {
case KVM_CREATE_IRQCHIP: {
if (vgic_present)
-   return kvm_vgic_create(kvm);
+   return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
else
return -ENXIO;
}
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f5788cf..4feac9a 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -231,7 +231,7 @@ struct kvm_exit_mmio;
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 int kvm_vgic_hyp_init(void);
 int kvm_vgic_init(struct kvm *kvm);
-int kvm_vgic_create(struct kvm *kvm);
+int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
@@ -282,7 +282,7 @@ static inline int kvm_vgic_init(struct kvm *kvm)
return 0;
 }
 
-static inline int kvm_vgic_create(struct kvm *kvm)
+static inline int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 68ac9c6..8f1daf2 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1832,7 +1832,7 @@ out:
return ret;
 }
 
-int kvm_vgic_create(struct kvm *kvm)
+int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
int i, vcpu_lock_idx = -1, ret = 0;
struct kvm_vcpu *vcpu;
@@ -2284,7 +2284,7 @@ static void vgic_destroy(struct kvm_device *dev)
 
 static int vgic_create(struct kvm_device *dev, u32 type)
 {
-   return kvm_vgic_create(dev-kvm);
+   return kvm_vgic_create(dev-kvm, type);
 }
 
 struct kvm_device_ops kvm_arm_vgic_v2_ops = {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/14] arm/arm64: KVM: make the maximum number of vCPUs a per-VM value

2014-06-19 Thread Andre Przywara
Currently the maximum number of vCPUs supported is a global value
limited by the used GIC model. GICv3 will lift this limit, but we
still need to observe it for guests using GICv2.
So the maximum number of vCPUs is per-VM value, depending on the
GIC model the guest uses.
Store and check the value in struct kvm_arch, but keep it down to
8 for now.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/include/asm/kvm_host.h   |1 +
 arch/arm/kvm/arm.c|6 ++
 arch/arm64/include/asm/kvm_host.h |3 +++
 virt/kvm/arm/vgic-v2.c|5 +
 virt/kvm/arm/vgic-v3.c|6 ++
 5 files changed, 21 insertions(+)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 8d30f05..49c07ea 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -67,6 +67,7 @@ struct kvm_arch {
 
/* Interrupt controller */
struct vgic_distvgic;
+   int max_vcpus;
 };
 
 #define KVM_NR_MEM_OBJS 40
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index fa37fa1..a291e63 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -142,6 +142,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
/* Mark the initial VMID generation invalid */
kvm-arch.vmid_gen = 0;
+   kvm-arch.max_vcpus = CONFIG_KVM_ARM_MAX_VCPUS;
 
return ret;
 out_free_stage2_pgd:
@@ -260,6 +261,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, 
unsigned int id)
int err;
struct kvm_vcpu *vcpu;
 
+   if (id = kvm-arch.max_vcpus) {
+   err = -EINVAL;
+   goto out;
+   }
+
vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
if (!vcpu) {
err = -ENOMEM;
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 4c84250..eef63b1 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -58,6 +58,9 @@ struct kvm_arch {
/* VTTBR value associated with above pgd and vmid */
u64vttbr;
 
+   /* The maximum number of vCPUs depends on the used GIC model */
+   int max_vcpus;
+
/* Interrupt controller */
struct vgic_distvgic;
 
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index f2c214a..4091078 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -164,11 +164,16 @@ static struct vgic_params vgic_v2_params;
 static bool vgic_v2_init_emul(struct kvm *kvm, int type)
 {
struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+   int nr_vcpus;
 
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
+   nr_vcpus = atomic_read(kvm-online_vcpus);
+   if (nr_vcpus  8)
+   return false;
vm_ops-get_lr = vgic_v2_get_lr;
vm_ops-set_lr = vgic_v2_set_lr;
+   kvm-arch.max_vcpus = 8;
return true;
}
 
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index f42961c..40d6817 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -171,11 +171,17 @@ static const struct vgic_ops vgic_v3_ops = {
 static bool vgic_v3_init_emul_compat(struct kvm *kvm, int type)
 {
struct vgic_vm_ops *vm_ops = kvm-arch.vgic.vm_ops;
+   int nr_vcpus;
 
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
+   nr_vcpus = atomic_read(kvm-online_vcpus);
+   if (nr_vcpus  8)
+   return false;
+
vm_ops-get_lr = vgic_v3_get_lr;
vm_ops-set_lr = vgic_v3_set_lr;
+   kvm-arch.max_vcpus = 8;
return true;
}
return false;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/14] arm/arm64: KVM: refactor MMIO accessors

2014-06-19 Thread Andre Przywara
The MMIO accessors for GICD_I[CS]ENABLER, GICD_I[CS]PENDR and
GICD_ICFGR behave very similiar in GICv3, although the way the
affected vCPU is determined differs.
Factor out a generic, backend-facing implementation and use small
wrappers in the current GICv2 emulation to ease code sharing later.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   93 ---
 1 file changed, 52 insertions(+), 41 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 2de58b3..2a59dff 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -398,35 +398,54 @@ static bool handle_mmio_raz_wi(struct kvm_vcpu *vcpu,
return false;
 }
 
-static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
-  struct kvm_exit_mmio *mmio,
-  phys_addr_t offset)
+static bool vgic_handle_enable_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio,
+  phys_addr_t offset, int vcpu_id, int access)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_enabled,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
+   u32 *reg;
+   int mode = ACCESS_READ_VALUE | access;
+   struct kvm_vcpu *target_vcpu = kvm_get_vcpu(kvm, vcpu_id);
+
+   reg = vgic_bitmap_get_reg(kvm-arch.vgic.irq_enabled, vcpu_id, offset);
+   vgic_reg_access(mmio, reg, offset, mode);
if (mmio-is_write) {
-   vgic_update_state(vcpu-kvm);
+   if (access  ACCESS_WRITE_CLEARBIT) {
+   if (offset  4) /* Force SGI enabled */
+   *reg |= 0x;
+   vgic_retire_disabled_irqs(target_vcpu);
+   }
+   vgic_update_state(kvm);
return true;
}
 
return false;
 }
 
+static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
+  struct kvm_exit_mmio *mmio,
+  phys_addr_t offset)
+{
+   return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
+ vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
+}
+
 static bool handle_mmio_clear_enable_reg(struct kvm_vcpu *vcpu,
 struct kvm_exit_mmio *mmio,
 phys_addr_t offset)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_enabled,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
+   return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
+ vcpu-vcpu_id, ACCESS_WRITE_CLEARBIT);
+}
+
+static bool vgic_handle_pending_reg(struct kvm *kvm, struct kvm_exit_mmio 
*mmio,
+   phys_addr_t offset, int vcpu_id, int access)
+{
+   u32 *reg;
+   int mode = ACCESS_READ_VALUE | access;
+
+   reg = vgic_bitmap_get_reg(kvm-arch.vgic.irq_state, vcpu_id, offset);
+   vgic_reg_access(mmio, reg, offset, mode);
if (mmio-is_write) {
-   if (offset  4) /* Force SGI enabled */
-   *reg |= 0x;
-   vgic_retire_disabled_irqs(vcpu);
-   vgic_update_state(vcpu-kvm);
+   vgic_update_state(kvm);
return true;
}
 
@@ -437,31 +456,16 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu 
*vcpu,
struct kvm_exit_mmio *mmio,
phys_addr_t offset)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_state,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
-   if (mmio-is_write) {
-   vgic_update_state(vcpu-kvm);
-   return true;
-   }
-
-   return false;
+   return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
+  vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
 }
 
 static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
  struct kvm_exit_mmio *mmio,
  phys_addr_t offset)
 {
-   u32 *reg = vgic_bitmap_get_reg(vcpu-kvm-arch.vgic.irq_state,
-  vcpu-vcpu_id, offset);
-   vgic_reg_access(mmio, reg, offset,
-   ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
-   if (mmio-is_write) {
-   vgic_update_state(vcpu-kvm);
-   return true;
-   }
-
+   return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
+  vcpu

[PATCH 14/14] arm/arm64: KVM: allow userland to request a virtual GICv3

2014-06-19 Thread Andre Przywara
With everything in place we allow userland to request the kernel
using a virtual GICv3 in the guest, which finally lifts the 8 vCPU
limit for a guest.
Also we provide the necessary support for guests setting the memory
addresses for the virtual distributor and redistributors.
This requires some userland code to make use of that feature and
explicitly ask for a virtual GICv3.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/include/uapi/asm/kvm.h |7 ++
 include/kvm/arm_vgic.h|4 ++--
 virt/kvm/arm/vgic-v3-emul.c   |3 +++
 virt/kvm/arm/vgic.c   |   46 ++---
 4 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index 5513de4..9a62081 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -77,6 +77,13 @@ struct kvm_regs {
 #define KVM_VGIC_V2_DIST_SIZE  0x1000
 #define KVM_VGIC_V2_CPU_SIZE   0x2000
 
+/* Supported VGICv3 address types  */
+#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST   3
+
+#define KVM_VGIC_V3_DIST_SIZE  SZ_64K
+#define KVM_VGIC_V3_REDIST_SIZE(2 * SZ_64K)
+
 #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
 #define KVM_ARM_VCPU_PSCI_0_2  2 /* CPU uses PSCI v0.2 */
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3b164ee..82e00a5 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -35,8 +35,8 @@
 #define VGIC_MAX_IRQS  1024
 
 /* Sanity checks... */
-#if (KVM_MAX_VCPUS  8)
-#error Invalid number of CPU interfaces
+#if (KVM_MAX_VCPUS  255)
+#error Too many KVM VCPUs, the VGIC only supports up to 255 VCPUs for now
 #endif
 
 #if (VGIC_NR_IRQS_LEGACY  31)
diff --git a/virt/kvm/arm/vgic-v3-emul.c b/virt/kvm/arm/vgic-v3-emul.c
index 68821fd..88c2cca 100644
--- a/virt/kvm/arm/vgic-v3-emul.c
+++ b/virt/kvm/arm/vgic-v3-emul.c
@@ -873,6 +873,9 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
case KVM_VGIC_V2_ADDR_TYPE_DIST:
case KVM_VGIC_V2_ADDR_TYPE_CPU:
return -ENXIO;
+   case KVM_VGIC_V3_ADDR_TYPE_DIST:
+   case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+   return 0;
}
break;
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 8a584e0..e3c7189 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1526,7 +1526,7 @@ static int vgic_ioaddr_assign(struct kvm *kvm, 
phys_addr_t *ioaddr,
 /**
  * kvm_vgic_addr - set or get vgic VM base addresses
  * @kvm:   pointer to the vm struct
- * @type:  the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX
+ * @type:  the VGIC addr type, one of KVM_VGIC_V[23]_ADDR_TYPE_XXX
  * @addr:  pointer to address value
  * @write: if true set the address in the VM address space, if false read the
  *  address
@@ -1540,29 +1540,49 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, 
u64 *addr, bool write)
 {
int r = 0;
struct vgic_dist *vgic = kvm-arch.vgic;
+   int type_needed;
+   phys_addr_t *addr_ptr, block_size;
 
mutex_lock(kvm-lock);
switch (type) {
case KVM_VGIC_V2_ADDR_TYPE_DIST:
-   if (write) {
-   r = vgic_ioaddr_assign(kvm, vgic-vgic_dist_base,
-  *addr, KVM_VGIC_V2_DIST_SIZE);
-   } else {
-   *addr = vgic-vgic_dist_base;
-   }
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+   addr_ptr = vgic-vgic_dist_base;
+   block_size = KVM_VGIC_V2_DIST_SIZE;
break;
case KVM_VGIC_V2_ADDR_TYPE_CPU:
-   if (write) {
-   r = vgic_ioaddr_assign(kvm, vgic-vgic_cpu_base,
-  *addr, KVM_VGIC_V2_CPU_SIZE);
-   } else {
-   *addr = vgic-vgic_cpu_base;
-   }
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+   addr_ptr = vgic-vgic_cpu_base;
+   block_size = KVM_VGIC_V2_CPU_SIZE;
break;
+#ifdef CONFIG_ARM_GIC_V3
+   case KVM_VGIC_V3_ADDR_TYPE_DIST:
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+   addr_ptr = vgic-vgic_dist_base;
+   block_size = KVM_VGIC_V3_DIST_SIZE;
+   break;
+   case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+   type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+   addr_ptr = vgic-vgic_redist_base;
+   block_size = KVM_VGIC_V3_REDIST_SIZE;
+   break;
+#endif
default:
r = -ENODEV;
+   goto out;
+   }
+
+   if (vgic-vgic_model

[PATCH 00/14] KVM GICv3 emulation

2014-06-19 Thread Andre Przywara
GICv3 is the ARM generic interrupt controller designed to overcome
some limits of the prevalent GICv2. Most notably it lifts the 8-CPU
limit. Though with recent patches from Marc there is support for
hosts to use a GICv3, the CPU limitation still applies to KVM guests,
since the current code emulates a GICv2 only.
Also, GICv2 backward compatibility being optional in GICv3, a number
of systems won't be able to run GICv2 guests.

This patch series provides code to emulate a GICv3 distributor and
redistributor for any KVM guest. It requires a GICv3 in the host to
work. With those patches one can run guests efficiently on any GICv3
host. It has the following features:
- Affinity routing (support for up to 255 VCPUs, more possible)
- System registers (as opposed to MMIO access)
- No ITS
- No priority support (as the GICv2 emulation)
- No save / restore support so far (will be added soon)

The first 10 patches actually refactor the current VGIC code to make
room for a different VGIC model to be dropped in with Patch 11/14.
The remaining patches connect the new model to the kernel backend and
the userland facing code.

The series goes on top of both Marc's GICv3 host support series as
well as his vgic-dyn patches.
The necessary patches for kvmtool to enable the guest's GICv3 will be
posted here as well.
There was some testing on the fast model with some I/O and interrupt
affinity shuffling in a Linux guest with a varying number of VCPUs.

Please review and test.
I would be grateful for people to test for GICv2 regressions also
(so on a GICv2 host with current kvmtool/qemu), as there is quite
some refactoring on that front.

Much of the code was inspired by Marc, so send all praises to him
(while I take the blame).

Cheers,
Andre.

Andre Przywara (14):
  arm/arm64: KVM: rework MPIDR assignment and add accessors
  arm/arm64: KVM: pass down user space provided GIC type into vGIC code
  arm/arm64: KVM: refactor vgic_handle_mmio() function
  arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones
  arm/arm64: KVM: introduce per-VM ops
  arm/arm64: KVM: make the maximum number of vCPUs a per-VM value
  arm/arm64: KVM: make the value of ICC_SRE_EL1 a per-VM variable
  arm/arm64: KVM: refactor MMIO accessors
  arm/arm64: KVM: split GICv2 specific emulation code from vgic.c
  arm/arm64: KVM: add opaque private pointer to MMIO accessors
  arm/arm64: KVM: add virtual GICv3 distributor emulation
  arm/arm64: KVM: add SGI system register trapping
  arm/arm64: KVM: enable kernel side of GICv3 emulation
  arm/arm64: KVM: allow userland to request a virtual GICv3

 arch/arm/include/asm/kvm_emulate.h   |2 +-
 arch/arm/include/asm/kvm_host.h  |3 +
 arch/arm/kvm/Makefile|1 +
 arch/arm/kvm/arm.c   |   23 +-
 arch/arm/kvm/coproc.c|   19 +
 arch/arm/kvm/psci.c  |   15 +-
 arch/arm64/include/asm/kvm_emulate.h |3 +-
 arch/arm64/include/asm/kvm_host.h|5 +
 arch/arm64/include/uapi/asm/kvm.h|7 +
 arch/arm64/kernel/asm-offsets.c  |1 +
 arch/arm64/kvm/Makefile  |2 +
 arch/arm64/kvm/sys_regs.c|   37 +-
 arch/arm64/kvm/vgic-v3-switch.S  |   14 +-
 include/kvm/arm_vgic.h   |   38 +-
 include/linux/irqchip/arm-gic-v3.h   |   26 +
 include/linux/kvm_host.h |1 +
 include/uapi/linux/kvm.h |1 +
 virt/kvm/arm/vgic-v2-emul.c  |  802 +++
 virt/kvm/arm/vgic-v2.c   |   22 +-
 virt/kvm/arm/vgic-v3-emul.c  |  898 ++
 virt/kvm/arm/vgic-v3.c   |  157 +-
 virt/kvm/arm/vgic.c  | 1017 +++---
 virt/kvm/arm/vgic.h  |  117 
 virt/kvm/kvm_main.c  |3 +
 24 files changed, 2346 insertions(+), 868 deletions(-)
 create mode 100644 virt/kvm/arm/vgic-v2-emul.c
 create mode 100644 virt/kvm/arm/vgic-v3-emul.c
 create mode 100644 virt/kvm/arm/vgic.h

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/14] arm/arm64: KVM: add opaque private pointer to MMIO accessors

2014-06-19 Thread Andre Przywara
For a GICv2 there is always only one (v)CPU involved: the one that
does the access. On a GICv3 the access to a CPU redistributor is
memory-mapped, but not banked, so the (v)CPU affected is determined by
looking at the MMIO address region being accessed.
To allow passing the affected CPU into the accessors, extend them to
take an opaque private pointer parameter.
For the current GICv2 emulation we ignore it and simply pass NULL
on the call.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic-v2-emul.c |   41 -
 virt/kvm/arm/vgic.c |   16 +---
 virt/kvm/arm/vgic.h |7 ---
 3 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/virt/kvm/arm/vgic-v2-emul.c b/virt/kvm/arm/vgic-v2-emul.c
index ba5f873..30d5c4c 100644
--- a/virt/kvm/arm/vgic-v2-emul.c
+++ b/virt/kvm/arm/vgic-v2-emul.c
@@ -41,7 +41,8 @@ static u8 *vgic_get_sgi_sources(struct vgic_dist *dist, int 
vcpu_id, int sgi)
 }
 
 static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
-struct kvm_exit_mmio *mmio, phys_addr_t offset)
+struct kvm_exit_mmio *mmio, phys_addr_t offset,
+void *private)
 {
u32 reg;
u32 word_offset = offset  3;
@@ -77,7 +78,7 @@ static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
 
 static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
   struct kvm_exit_mmio *mmio,
-  phys_addr_t offset)
+  phys_addr_t offset, void *private)
 {
return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
  vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
@@ -85,7 +86,7 @@ static bool handle_mmio_set_enable_reg(struct kvm_vcpu *vcpu,
 
 static bool handle_mmio_clear_enable_reg(struct kvm_vcpu *vcpu,
 struct kvm_exit_mmio *mmio,
-phys_addr_t offset)
+phys_addr_t offset, void *private)
 {
return vgic_handle_enable_reg(vcpu-kvm, mmio, offset,
  vcpu-vcpu_id, ACCESS_WRITE_CLEARBIT);
@@ -93,7 +94,7 @@ static bool handle_mmio_clear_enable_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio,
-   phys_addr_t offset)
+   phys_addr_t offset, void *private)
 {
return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
   vcpu-vcpu_id, ACCESS_WRITE_SETBIT);
@@ -101,7 +102,7 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
  struct kvm_exit_mmio *mmio,
- phys_addr_t offset)
+ phys_addr_t offset, void *private)
 {
return vgic_handle_pending_reg(vcpu-kvm, mmio, offset,
   vcpu-vcpu_id, ACCESS_WRITE_CLEARBIT);
@@ -109,7 +110,7 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_priority_reg(struct kvm_vcpu *vcpu,
 struct kvm_exit_mmio *mmio,
-phys_addr_t offset)
+phys_addr_t offset, void *private)
 {
u32 *reg;
 
@@ -169,7 +170,7 @@ static void vgic_set_target_reg(struct kvm *kvm, u32 val, 
int irq)
 
 static bool handle_mmio_target_reg(struct kvm_vcpu *vcpu,
   struct kvm_exit_mmio *mmio,
-  phys_addr_t offset)
+  phys_addr_t offset, void *private)
 {
u32 reg;
 
@@ -197,7 +198,8 @@ static bool handle_mmio_target_reg(struct kvm_vcpu *vcpu,
 }
 
 static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
-   struct kvm_exit_mmio *mmio, phys_addr_t offset)
+   struct kvm_exit_mmio *mmio, phys_addr_t offset,
+   void *private)
 {
u32 *reg;
 
@@ -208,7 +210,8 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
 }
 
 static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
-   struct kvm_exit_mmio *mmio, phys_addr_t offset)
+   struct kvm_exit_mmio *mmio, phys_addr_t offset,
+   void *private)
 {
u32 reg;
vgic_reg_access(mmio, reg, offset,
@@ -281,7 +284,7 @@ static bool write_set_clear_sgi_pend_reg(struct kvm_vcpu 
*vcpu,
 
 static bool handle_mmio_sgi_set(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio

[PATCH 13/14] arm/arm64: KVM: enable kernel side of GICv3 emulation

2014-06-19 Thread Andre Przywara
With all the necessary GICv3 emulation code in place, we can now
connect the code to the GICv3 backend in the kernel.
The LR register handling is different depending on the emulated GIC
model, so provide different implementations for each.
Also allow non-v2-compatible GICv3 implementations (which don't
provide MMIO regions for the virtual CPU interface in the DT), but
restrict those hosts to use GICv3 guests only.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic-v3.c |  138 ++--
 virt/kvm/arm/vgic.c|2 +
 2 files changed, 112 insertions(+), 28 deletions(-)

diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 7d9c85e..d26d12f 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -34,6 +34,7 @@
 #define GICH_LR_VIRTUALID  (0x3ffUL  0)
 #define GICH_LR_PHYSID_CPUID_SHIFT (10)
 #define GICH_LR_PHYSID_CPUID   (7UL  GICH_LR_PHYSID_CPUID_SHIFT)
+#define ICH_LR_VIRTUALID_MASK  (BIT_ULL(32) - 1)
 
 /*
  * LRs are stored in reverse order in memory. make sure we index them
@@ -43,7 +44,35 @@
 
 static u32 ich_vtr_el2;
 
-static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
+static u64 sync_lr_val(u8 state)
+{
+   u64 lr_val = 0;
+
+   if (state  LR_STATE_PENDING)
+   lr_val |= ICH_LR_PENDING_BIT;
+   if (state  LR_STATE_ACTIVE)
+   lr_val |= ICH_LR_ACTIVE_BIT;
+   if (state  LR_EOI_INT)
+   lr_val |= ICH_LR_EOI;
+
+   return lr_val;
+}
+
+static u8 sync_lr_state(u64 lr_val)
+{
+   u8 state = 0;
+
+   if (lr_val  ICH_LR_PENDING_BIT)
+   state |= LR_STATE_PENDING;
+   if (lr_val  ICH_LR_ACTIVE_BIT)
+   state |= LR_STATE_ACTIVE;
+   if (lr_val  ICH_LR_EOI)
+   state |= LR_EOI_INT;
+
+   return state;
+}
+
+static struct vgic_lr vgic_v2_on_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 {
struct vgic_lr lr_desc;
u64 val = vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
@@ -53,30 +82,53 @@ static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu 
*vcpu, int lr)
lr_desc.source  = (val  GICH_LR_PHYSID_CPUID_SHIFT)  0x7;
else
lr_desc.source = 0;
-   lr_desc.state   = 0;
+   lr_desc.state   = sync_lr_state(val);
 
-   if (val  ICH_LR_PENDING_BIT)
-   lr_desc.state |= LR_STATE_PENDING;
-   if (val  ICH_LR_ACTIVE_BIT)
-   lr_desc.state |= LR_STATE_ACTIVE;
-   if (val  ICH_LR_EOI)
-   lr_desc.state |= LR_EOI_INT;
+   return lr_desc;
+}
+
+static struct vgic_lr vgic_v3_on_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
+{
+   struct vgic_lr lr_desc;
+   u64 val = vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)];
+
+   lr_desc.irq = val  ICH_LR_VIRTUALID_MASK;
+   lr_desc.source  = 0;
+   lr_desc.state   = sync_lr_state(val);
 
return lr_desc;
 }
 
-static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
-  struct vgic_lr lr_desc)
+static void vgic_v3_on_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
+struct vgic_lr lr_desc)
 {
-   u64 lr_val = (((u32)lr_desc.source  GICH_LR_PHYSID_CPUID_SHIFT) |
- lr_desc.irq);
+   u64 lr_val;
 
-   if (lr_desc.state  LR_STATE_PENDING)
-   lr_val |= ICH_LR_PENDING_BIT;
-   if (lr_desc.state  LR_STATE_ACTIVE)
-   lr_val |= ICH_LR_ACTIVE_BIT;
-   if (lr_desc.state  LR_EOI_INT)
-   lr_val |= ICH_LR_EOI;
+   lr_val = lr_desc.irq;
+
+   /*
+* currently all guest IRQs are Group1, as Group0 would result
+* in a FIQ in the guest, which it wouldn't expect.
+* Eventually we want to make this configurable, so we may revisit
+* this in the future.
+*/
+   lr_val |= ICH_LR_GROUP;
+
+   lr_val |= sync_lr_val(lr_desc.state);
+
+   vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val;
+}
+
+static void vgic_v2_on_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
+struct vgic_lr lr_desc)
+{
+   u64 lr_val;
+
+   lr_val = lr_desc.irq;
+
+   lr_val |= (u32)lr_desc.source  GICH_LR_PHYSID_CPUID_SHIFT;
+
+   lr_val |= sync_lr_val(lr_desc.state);
 
vcpu-arch.vgic_cpu.vgic_v3.vgic_lr[LR_INDEX(lr)] = lr_val;
 }
@@ -145,9 +197,8 @@ static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct 
vgic_vmcr *vmcrp)
 
 static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 {
-   struct vgic_v3_cpu_if *vgic_v3;
+   struct vgic_v3_cpu_if *vgic_v3 = vcpu-arch.vgic_cpu.vgic_v3;
 
-   vgic_v3 = vcpu-arch.vgic_cpu.vgic_v3;
/*
 * By forcing VMCR to zero, the GIC will restore the binary
 * points to their reset values. Anything else resets to zero
@@ -155,7 +206,14 @@ static void vgic_v3_enable(struct kvm_vcpu *vcpu)
 */
vgic_v3-vgic_vmcr

[PATCH 04/14] arm/arm64: KVM: wrap 64 bit MMIO accesses with two 32 bit ones

2014-06-19 Thread Andre Przywara
Some GICv3 registers can and will be accessed as 64 bit registers.
Currently the register handling code can only deal with 32 bit
accesses, so we do two consecutive calls to cover this.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 virt/kvm/arm/vgic.c |   48 +---
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 4c6b212..b3cf4c7 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -906,6 +906,48 @@ static bool vgic_validate_access(const struct vgic_dist 
*dist,
 }
 
 /*
+ * Call the respective handler function for the given range.
+ * We split up any 64 bit accesses into two consecutive 32 bit
+ * handler calls and merge the result afterwards.
+ */
+static bool call_range_handler(struct kvm_vcpu *vcpu,
+  struct kvm_exit_mmio *mmio,
+  unsigned long offset,
+  const struct mmio_range *range)
+{
+   u32 *data32 = (void *)mmio-data;
+   struct kvm_exit_mmio mmio32;
+   bool ret;
+
+   if (likely(mmio-len = 4))
+   return range-handle_mmio(vcpu, mmio, offset);
+
+   /*
+* We assume that any access greater than 4 bytes is actually
+* 8 bytes long, caused by a 64-bit access
+*/
+
+   mmio32.len = 4;
+   mmio32.is_write = mmio-is_write;
+
+   mmio32.phys_addr = mmio-phys_addr + 4;
+   if (mmio-is_write)
+   *(u32 *)mmio32.data = data32[1];
+   ret = range-handle_mmio(vcpu, mmio32, offset + 4);
+   if (!mmio-is_write)
+   data32[1] = *(u32 *)mmio32.data;
+
+   mmio32.phys_addr = mmio-phys_addr;
+   if (mmio-is_write)
+   *(u32 *)mmio32.data = data32[0];
+   ret |= range-handle_mmio(vcpu, mmio32, offset);
+   if (!mmio-is_write)
+   data32[0] = *(u32 *)mmio32.data;
+
+   return ret;
+}
+
+/*
  * vgic_handle_mmio_range - handle an in-kernel MMIO access
  * @vcpu:  pointer to the vcpu performing the access
  * @run:   pointer to the kvm_run structure
@@ -936,10 +978,10 @@ static bool vgic_handle_mmio_range(struct kvm_vcpu *vcpu, 
struct kvm_run *run,
spin_lock(vcpu-kvm-arch.vgic.lock);
offset -= range-base;
if (vgic_validate_access(dist, range, offset)) {
-   updated_state = range-handle_mmio(vcpu, mmio, offset);
+   updated_state = call_range_handler(vcpu, mmio, offset, range);
} else {
-   vgic_reg_access(mmio, NULL, offset,
-   ACCESS_READ_RAZ | ACCESS_WRITE_IGNORED);
+   if (!mmio-is_write)
+   memset(mmio-data, 0, mmio-len);
updated_state = false;
}
spin_unlock(vcpu-kvm-arch.vgic.lock);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/14] arm/arm64: KVM: rework MPIDR assignment and add accessors

2014-06-19 Thread Andre Przywara
The virtual MPIDR registers (containing topology information) for the
guest are currently mapped linearily to the vcpu_id. Improve this
mapping for arm64 by using three levels to not artificially limit the
number of vCPUs. Also add an accessor to later allow easier access to
a vCPU with a given MPIDR.
Use this new accessor in the PSCI emulation.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm/include/asm/kvm_emulate.h   |2 +-
 arch/arm/include/asm/kvm_host.h  |2 ++
 arch/arm/kvm/arm.c   |   15 +++
 arch/arm/kvm/psci.c  |   15 ---
 arch/arm64/include/asm/kvm_emulate.h |3 ++-
 arch/arm64/include/asm/kvm_host.h|2 ++
 arch/arm64/kvm/sys_regs.c|   11 +--
 7 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/kvm_emulate.h 
b/arch/arm/include/asm/kvm_emulate.h
index 0fa90c9..6b528e4 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -159,7 +159,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu 
*vcpu)
 
 static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
 {
-   return vcpu-arch.cp15[c0_MPIDR];
+   return vcpu-arch.cp15[c0_MPIDR]  MPIDR_HWID_BITMASK;
 }
 
 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index d6d5227..8d30f05 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -236,4 +236,6 @@ int kvm_perf_teardown(void);
 u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
 int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
 
+struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9b3957d..9ffe962 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1027,6 +1027,21 @@ static void check_kvm_target_cpu(void *ret)
*(int *)ret = kvm_target_cpu();
 }
 
+struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
+{
+   unsigned long c_mpidr;
+   struct kvm_vcpu *vcpu;
+   int i;
+
+   mpidr = MPIDR_HWID_BITMASK;
+   kvm_for_each_vcpu(i, vcpu, kvm) {
+   c_mpidr = kvm_vcpu_get_mpidr(vcpu);
+   if (c_mpidr == mpidr)
+   return vcpu;
+   }
+   return NULL;
+}
+
 /**
  * Initialize Hyp-mode and memory mappings on all CPUs.
  */
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 09cf377..49f0992 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -21,6 +21,7 @@
 #include asm/cputype.h
 #include asm/kvm_emulate.h
 #include asm/kvm_psci.h
+#include asm/kvm_host.h
 
 /*
  * This is an implementation of the Power State Coordination Interface
@@ -65,25 +66,17 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
 static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 {
struct kvm *kvm = source_vcpu-kvm;
-   struct kvm_vcpu *vcpu = NULL, *tmp;
+   struct kvm_vcpu *vcpu = NULL;
wait_queue_head_t *wq;
unsigned long cpu_id;
unsigned long context_id;
-   unsigned long mpidr;
phys_addr_t target_pc;
-   int i;
 
-   cpu_id = *vcpu_reg(source_vcpu, 1);
+   cpu_id = *vcpu_reg(source_vcpu, 1)  MPIDR_HWID_BITMASK;
if (vcpu_mode_is_32bit(source_vcpu))
cpu_id = ~((u32) 0);
 
-   kvm_for_each_vcpu(i, tmp, kvm) {
-   mpidr = kvm_vcpu_get_mpidr(tmp);
-   if ((mpidr  MPIDR_HWID_BITMASK) == (cpu_id  
MPIDR_HWID_BITMASK)) {
-   vcpu = tmp;
-   break;
-   }
-   }
+   vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id);
 
/*
 * Make sure the caller requested a valid CPU and that the CPU is
diff --git a/arch/arm64/include/asm/kvm_emulate.h 
b/arch/arm64/include/asm/kvm_emulate.h
index dd8ecfc..685ea1b 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -27,6 +27,7 @@
 #include asm/kvm_arm.h
 #include asm/kvm_mmio.h
 #include asm/ptrace.h
+#include asm/cputype.h
 
 unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, u8 reg_num);
 unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu);
@@ -179,7 +180,7 @@ static inline u8 kvm_vcpu_trap_get_fault(const struct 
kvm_vcpu *vcpu)
 
 static inline unsigned long kvm_vcpu_get_mpidr(struct kvm_vcpu *vcpu)
 {
-   return vcpu_sys_reg(vcpu, MPIDR_EL1);
+   return vcpu_sys_reg(vcpu, MPIDR_EL1)  MPIDR_HWID_BITMASK;
 }
 
 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 4ae9213..4c84250 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -228,4 +228,6 @@ static inline void vgic_arch_setup(const struct vgic_params 
*vgic

[PATCH 3/4] kvmtool: add support for supplying GICv3 redistributor addresses

2014-06-19 Thread Andre Przywara
The code currently is assuming fixed sized memory regions for the
distributor and CPU interface. GICv3 needs a dynamic allocation of
it's redistributor region, since it's size depends on the number of
vCPUs.
Also add the necessary code to create a GICv3 IRQ chip instance.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/arm/aarch64/include/kvm/kvm-arch.h |6 ++
 tools/kvm/arm/gic.c  |   29 --
 tools/kvm/arm/include/arm-common/kvm-arch.h  |   11 ++
 tools/kvm/arm/kvm-cpu.c  |4 +++-
 4 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/tools/kvm/arm/aarch64/include/kvm/kvm-arch.h 
b/tools/kvm/arm/aarch64/include/kvm/kvm-arch.h
index 4925736..42d0fd6 100644
--- a/tools/kvm/arm/aarch64/include/kvm/kvm-arch.h
+++ b/tools/kvm/arm/aarch64/include/kvm/kvm-arch.h
@@ -3,6 +3,12 @@
 
 #define ARM_GIC_DIST_SIZE  0x1
 #define ARM_GIC_CPUI_SIZE  0x2
+/*
+ * On a GICv3 there must be one redistributor per vCPU.
+ * The value here is the size for one, we multiply this at runtime with
+ * the number of requested vCPUs to get the actual size.
+ */
+#define ARM_GIC_REDIST_SIZE0x2
 
 #define ARM_KERN_OFFSET(kvm)   ((kvm)-cfg.arch.aarch32_guest  ?   \
0x8000  :   \
diff --git a/tools/kvm/arm/gic.c b/tools/kvm/arm/gic.c
index 770c6e7..5141868 100644
--- a/tools/kvm/arm/gic.c
+++ b/tools/kvm/arm/gic.c
@@ -11,6 +11,7 @@
 static int irq_ids;
 static int gic_fd = -1;
 static u64 cpu_if_addr = ARM_GIC_CPUI_BASE;
+static int nr_redists = 0;
 
 int gic__alloc_irqnum(void)
 {
@@ -27,6 +28,7 @@ static int gic__create_device(struct kvm *kvm, u32 type)
int err;
u32 offset = 0;
u64 dist_addr = ARM_GIC_DIST_BASE;
+   u64 redist_addr;
struct kvm_create_device gic_device = {
.type   = type,
};
@@ -41,9 +43,13 @@ static int gic__create_device(struct kvm *kvm, u32 type)
};
struct kvm_device_attr dist_attr = {
.group  = KVM_DEV_ARM_VGIC_GRP_ADDR,
-   .attr   = KVM_VGIC_V2_ADDR_TYPE_DIST,
.addr   = (u64)(unsigned long)dist_addr,
};
+   struct kvm_device_attr redist_attr = {
+   .group  = KVM_DEV_ARM_VGIC_GRP_ADDR,
+   .attr   = KVM_VGIC_V3_ADDR_TYPE_REDIST,
+   .addr   = (u64)(unsigned long)redist_addr,
+   };
 
err = ioctl(kvm-vm_fd, KVM_CREATE_DEVICE, gic_device);
if (err)
@@ -64,13 +70,23 @@ static int gic__create_device(struct kvm *kvm, u32 type)
err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, cpu_if_attr);
if (err)
return err;
+   dist_attr.attr = KVM_VGIC_V2_ADDR_TYPE_DIST;
pr_info(creating GICv2 KVM device);
break;
+   case KVM_DEV_TYPE_ARM_VGIC_V3:
+   dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST;
+   redist_addr = dist_addr - nr_redists * ARM_GIC_REDIST_SIZE;
+   break;
default:
return -ENODEV;
}
 
err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, dist_attr);
+   if (err)
+   return err;
+
+   if (type == KVM_DEV_TYPE_ARM_VGIC_V3)
+   err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, redist_attr);
 
return err;
 }
@@ -166,17 +182,26 @@ void gic__generate_fdt_nodes(void *fdt, u32 phandle, u32 
type)
u64 reg_prop[] = {
cpu_to_fdt64(ARM_GIC_DIST_BASE),
cpu_to_fdt64(ARM_GIC_DIST_SIZE),
-   cpu_to_fdt64(cpu_if_addr), cpu_to_fdt64(ARM_GIC_CPUI_SIZE),
+   0, 0,   /* to be filled */
};
 
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
compatible = arm,cortex-a15-gic;
+   reg_prop[2] = cpu_if_addr;
+   reg_prop[3] = ARM_GIC_CPUI_SIZE;
pr_info(creating FDT for a GICv2);
break;
+   case KVM_DEV_TYPE_ARM_VGIC_V3:
+   compatible = arm,gic-v3;
+   reg_prop[2] = ARM_GIC_DIST_BASE - nr_redists * 
ARM_GIC_REDIST_SIZE;
+   reg_prop[3] = ARM_GIC_REDIST_SIZE * nr_redists;
+   break;
default:
return;
}
+   reg_prop[2] = cpu_to_fdt64(reg_prop[2]);
+   reg_prop[3] = cpu_to_fdt64(reg_prop[3]);
 
_FDT(fdt_begin_node(fdt, intc));
_FDT(fdt_property_string(fdt, compatible, compatible));
diff --git a/tools/kvm/arm/include/arm-common/kvm-arch.h 
b/tools/kvm/arm/include/arm-common/kvm-arch.h
index 72b204f..c7bfd9a 100644
--- a/tools/kvm/arm/include/arm-common/kvm-arch.h
+++ b/tools/kvm/arm/include/arm-common/kvm-arch.h
@@ -15,10 +15,8 @@
 
 #define ARM_GIC_DIST_BASE  (ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
 #define ARM_GIC_CPUI_BASE  (ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
-#define ARM_GIC_SIZE

[PATCH 2/4] kvmtool: prepare for instantiating different IRQ chip devices

2014-06-19 Thread Andre Przywara
Extend the vGIC handling code to deal with different IRQ chip devices
instead of hard-coding the GICv2 in.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/arm/aarch64/arm-cpu.c|2 +-
 tools/kvm/arm/gic.c|   59 
 tools/kvm/arm/include/arm-common/gic.h |4 +--
 tools/kvm/arm/kvm.c|2 +-
 tools/kvm/virtio/mmio.c|2 +-
 5 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c
index ce5ea2f..35771e0 100644
--- a/tools/kvm/arm/aarch64/arm-cpu.c
+++ b/tools/kvm/arm/aarch64/arm-cpu.c
@@ -12,7 +12,7 @@
 static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
 {
int timer_interrupts[4] = {13, 14, 11, 10};
-   gic__generate_fdt_nodes(fdt, gic_phandle);
+   gic__generate_fdt_nodes(fdt, gic_phandle, KVM_DEV_TYPE_ARM_VGIC_V2);
timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
 }
 
diff --git a/tools/kvm/arm/gic.c b/tools/kvm/arm/gic.c
index c92deaa..770c6e7 100644
--- a/tools/kvm/arm/gic.c
+++ b/tools/kvm/arm/gic.c
@@ -22,13 +22,13 @@ int gic__alloc_irqnum(void)
return irq;
 }
 
-static int gic__create_device(struct kvm *kvm)
+static int gic__create_device(struct kvm *kvm, u32 type)
 {
int err;
u32 offset = 0;
u64 dist_addr = ARM_GIC_DIST_BASE;
struct kvm_create_device gic_device = {
-   .type   = KVM_DEV_TYPE_ARM_VGIC_V2,
+   .type   = type,
};
struct kvm_device_attr offset_attr = {
.group  = KVM_DEV_ARM_VGIC_GRP_ADDR_OFFSET,
@@ -51,19 +51,28 @@ static int gic__create_device(struct kvm *kvm)
 
gic_fd = gic_device.fd;
 
-   if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, offset_attr)) {
-   err = ioctl(gic_fd, KVM_GET_DEVICE_ATTR, offset_attr);
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, offset_attr)) {
+   err = ioctl(gic_fd, KVM_GET_DEVICE_ATTR, offset_attr);
+   if (err)
+   return err;
+   }
+
+   cpu_if_addr += offset;
+
+   err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, cpu_if_attr);
if (err)
return err;
+   pr_info(creating GICv2 KVM device);
+   break;
+   default:
+   return -ENODEV;
}
 
-   cpu_if_addr += offset;
+   err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, dist_attr);
 
-   err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, cpu_if_attr);
-   if (err)
-   return err;
-
-   return ioctl(gic_fd, KVM_SET_DEVICE_ATTR, dist_attr);
+   return err;
 }
 
 static int gic__create_irqchip(struct kvm *kvm)
@@ -94,7 +103,7 @@ static int gic__create_irqchip(struct kvm *kvm)
return err;
 }
 
-int gic__init_irqchip(struct kvm *kvm)
+static int gicv2__init_irqchip(struct kvm *kvm)
 {
int err;
int psz;
@@ -113,13 +122,22 @@ int gic__init_irqchip(struct kvm *kvm)
}
 
/* Try the new way first, and fallback on legacy method otherwise */
-   err = gic__create_device(kvm);
+   err = gic__create_device(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
if (err)
err = gic__create_irqchip(kvm);
 
return err;
 }
 
+int gic__init_irqchip(struct kvm *kvm, u32 type)
+{
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   return gicv2__init_irqchip(kvm);
+   }
+   return -ENODEV;
+}
+
 static int gic__init_max_irq(struct kvm *kvm)
 {
u32 nr_irqs = ALIGN(irq_ids, 32) + GIC_SPI_IRQ_BASE;
@@ -142,15 +160,26 @@ static int gic__init_max_irq(struct kvm *kvm)
 }
 late_init(gic__init_max_irq)
 
-void gic__generate_fdt_nodes(void *fdt, u32 phandle)
+void gic__generate_fdt_nodes(void *fdt, u32 phandle, u32 type)
 {
+   const char *compatible;
u64 reg_prop[] = {
-   cpu_to_fdt64(ARM_GIC_DIST_BASE), 
cpu_to_fdt64(ARM_GIC_DIST_SIZE),
+   cpu_to_fdt64(ARM_GIC_DIST_BASE),
+   cpu_to_fdt64(ARM_GIC_DIST_SIZE),
cpu_to_fdt64(cpu_if_addr), cpu_to_fdt64(ARM_GIC_CPUI_SIZE),
};
 
+   switch (type) {
+   case KVM_DEV_TYPE_ARM_VGIC_V2:
+   compatible = arm,cortex-a15-gic;
+   pr_info(creating FDT for a GICv2);
+   break;
+   default:
+   return;
+   }
+
_FDT(fdt_begin_node(fdt, intc));
-   _FDT(fdt_property_string(fdt, compatible, arm,cortex-a15-gic));
+   _FDT(fdt_property_string(fdt, compatible, compatible));
_FDT(fdt_property_cell(fdt, #interrupt-cells, GIC_FDT_IRQ_NUM_CELLS));
_FDT(fdt_property(fdt, interrupt-controller, NULL, 0));
_FDT(fdt_property(fdt, reg, reg_prop, sizeof(reg_prop)));
diff --git a/tools/kvm/arm/include/arm-common/gic.h 
b/tools

[PATCH 4/4] kvmtool: add command line parameter to instantiate a vGICv3

2014-06-19 Thread Andre Przywara
Add the command line parameter --gicv3 to request GICv3 emulation
in the kernel. Connect that to the already existing GICv3 code.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 tools/kvm/arm/aarch64/arm-cpu.c|5 -
 .../kvm/arm/aarch64/include/kvm/kvm-config-arch.h  |4 +++-
 tools/kvm/arm/gic.c|   17 +
 tools/kvm/arm/include/arm-common/kvm-config-arch.h |1 +
 tools/kvm/arm/kvm.c|4 +++-
 5 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/tools/kvm/arm/aarch64/arm-cpu.c b/tools/kvm/arm/aarch64/arm-cpu.c
index 35771e0..e3514ea 100644
--- a/tools/kvm/arm/aarch64/arm-cpu.c
+++ b/tools/kvm/arm/aarch64/arm-cpu.c
@@ -12,7 +12,10 @@
 static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
 {
int timer_interrupts[4] = {13, 14, 11, 10};
-   gic__generate_fdt_nodes(fdt, gic_phandle, KVM_DEV_TYPE_ARM_VGIC_V2);
+   gic__generate_fdt_nodes(fdt, gic_phandle,
+   kvm-cfg.arch.gicv3 ?
+   KVM_DEV_TYPE_ARM_VGIC_V3 :
+   KVM_DEV_TYPE_ARM_VGIC_V2);
timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
 }
 
diff --git a/tools/kvm/arm/aarch64/include/kvm/kvm-config-arch.h 
b/tools/kvm/arm/aarch64/include/kvm/kvm-config-arch.h
index 89860ae..780a6d1 100644
--- a/tools/kvm/arm/aarch64/include/kvm/kvm-config-arch.h
+++ b/tools/kvm/arm/aarch64/include/kvm/kvm-config-arch.h
@@ -3,7 +3,9 @@
 
 #define ARM_OPT_ARCH_RUN(cfg)  \
OPT_BOOLEAN('\0', aarch32, (cfg)-aarch32_guest, \
-   Run AArch32 guest),
+   Run AArch32 guest),   \
+   OPT_BOOLEAN('\0', gicv3, (cfg)-gicv3,   \
+   use a GICv3 interrupt controller in the guest),
 
 #include arm-common/kvm-config-arch.h
 
diff --git a/tools/kvm/arm/gic.c b/tools/kvm/arm/gic.c
index 5141868..15dc99d 100644
--- a/tools/kvm/arm/gic.c
+++ b/tools/kvm/arm/gic.c
@@ -76,6 +76,7 @@ static int gic__create_device(struct kvm *kvm, u32 type)
case KVM_DEV_TYPE_ARM_VGIC_V3:
dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST;
redist_addr = dist_addr - nr_redists * ARM_GIC_REDIST_SIZE;
+   pr_info(creating GICv3 KVM device);
break;
default:
return -ENODEV;
@@ -119,6 +120,17 @@ static int gic__create_irqchip(struct kvm *kvm)
return err;
 }
 
+static int gicv3__init_irqchip(struct kvm *kvm)
+{
+   if (kvm-nrcpus  255) {
+   pr_warning(%d CPUS greater than maximum of %d -- truncating\n,
+   kvm-nrcpus, 255);
+   kvm-nrcpus = 255;
+   }
+
+   return gic__create_device(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
+}
+
 static int gicv2__init_irqchip(struct kvm *kvm)
 {
int err;
@@ -150,6 +162,9 @@ int gic__init_irqchip(struct kvm *kvm, u32 type)
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V2:
return gicv2__init_irqchip(kvm);
+   case KVM_DEV_TYPE_ARM_VGIC_V3:
+   nr_redists = kvm-cfg.nrcpus;
+   return gicv3__init_irqchip(kvm);
}
return -ENODEV;
 }
@@ -196,6 +211,8 @@ void gic__generate_fdt_nodes(void *fdt, u32 phandle, u32 
type)
compatible = arm,gic-v3;
reg_prop[2] = ARM_GIC_DIST_BASE - nr_redists * 
ARM_GIC_REDIST_SIZE;
reg_prop[3] = ARM_GIC_REDIST_SIZE * nr_redists;
+   pr_info(creating FDT for a GICv3 with %d redistributors,
+   nr_redists);
break;
default:
return;
diff --git a/tools/kvm/arm/include/arm-common/kvm-config-arch.h 
b/tools/kvm/arm/include/arm-common/kvm-config-arch.h
index f3baf39..088b012 100644
--- a/tools/kvm/arm/include/arm-common/kvm-config-arch.h
+++ b/tools/kvm/arm/include/arm-common/kvm-config-arch.h
@@ -7,6 +7,7 @@ struct kvm_config_arch {
const char *dump_dtb_filename;
unsigned int force_cntfrq;
bool aarch32_guest;
+   bool gicv3;
 };
 
 #define OPT_ARCH_RUN(pfx, cfg) 
\
diff --git a/tools/kvm/arm/kvm.c b/tools/kvm/arm/kvm.c
index faf4702..3858170 100644
--- a/tools/kvm/arm/kvm.c
+++ b/tools/kvm/arm/kvm.c
@@ -80,6 +80,8 @@ void kvm__arch_init(struct kvm *kvm, const char 
*hugetlbfs_path, u64 ram_size)
MADV_MERGEABLE);
 
/* Initialise the virtual GIC. */
-   if (gic__init_irqchip(kvm, KVM_DEV_TYPE_ARM_VGIC_V2))
+   if (gic__init_irqchip(kvm, kvm-cfg.arch.gicv3 ?
+  KVM_DEV_TYPE_ARM_VGIC_V3 :
+  KVM_DEV_TYPE_ARM_VGIC_V2))
die(Failed to initialise virtual GIC);
 }
-- 
1.7.9.5

--
To unsubscribe from this list: send

[PATCH 0/4] kvmtool: Add GICv3 emulation support

2014-06-19 Thread Andre Przywara
This is a first version of the kvmtool changes needed for GICv3
emulation. Allows testing of the GICv3 emulation code and allows
creating guests with more than 8 VCPUs (given that in the host
CONFIG_KVM_ARM_MAX_VCPUS and in the guest CONFIG_NR_CPUS have been
raised accordingly).
Use --gicv3 to create a GICv3 IRQ chip in the guest.

This goes on top of Marc's kvmtool-vgic-dyn branch on kernel.org:
https://git.kernel.org/cgit/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/kvmtool-vgic-dyn

This is not meant for merging right now, as it eventually needs to
be rebased on a more recent kvmtool version first.

Cheers,
Andre

Andre Przywara (4):
  kvmtool: public header definitions from GICv3 emulation patch series
  kvmtool: prepare for instantiating different IRQ chip devices
  kvmtool: add support for supplying GICv3 redistributor addresses
  kvmtool: add command line parameter to instantiate a vGICv3

 arch/arm64/include/uapi/asm/kvm.h  |6 ++
 include/uapi/linux/kvm.h   |1 +
 tools/kvm/arm/aarch64/arm-cpu.c|5 +-
 tools/kvm/arm/aarch64/include/kvm/kvm-arch.h   |6 ++
 .../kvm/arm/aarch64/include/kvm/kvm-config-arch.h  |4 +-
 tools/kvm/arm/gic.c|  101 +---
 tools/kvm/arm/include/arm-common/gic.h |4 +-
 tools/kvm/arm/include/arm-common/kvm-arch.h|   11 ++-
 tools/kvm/arm/include/arm-common/kvm-config-arch.h |1 +
 tools/kvm/arm/kvm-cpu.c|4 +-
 tools/kvm/arm/kvm.c|4 +-
 tools/kvm/virtio/mmio.c|2 +-
 12 files changed, 123 insertions(+), 26 deletions(-)

-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] kvmtool: public header definitions from GICv3 emulation patch series

2014-06-19 Thread Andre Przywara
This pulls the necessary defines for the GICv3 constants from the
Linux tree into kvmtool for now. Should be obsolete as soon as
the vGICv3 patches are upstream and kvmtool is rebased on top of
it.

Signed-off-by: Andre Przywara andre.przyw...@arm.com
---
 arch/arm64/include/uapi/asm/kvm.h |6 ++
 include/uapi/linux/kvm.h  |1 +
 2 files changed, 7 insertions(+)

diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index 0dc731d..2c26821 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -75,6 +75,12 @@ struct kvm_regs {
 #define KVM_VGIC_V2_DIST_SIZE  0x1000
 #define KVM_VGIC_V2_CPU_SIZE   0x2000
 
+#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST   3
+
+#define KVM_VGIC_V3_DIST_SIZE  0x1
+#define KVM_VGIC_V3_REDIST_SIZE0x2
+
 #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
 
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 932d7f2..3af4b60 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -855,6 +855,7 @@ struct kvm_device_attr {
 #define   KVM_DEV_VFIO_GROUP_ADD   1
 #define   KVM_DEV_VFIO_GROUP_DEL   2
 #define KVM_DEV_TYPE_ARM_VGIC_V2   5
+#define KVM_DEV_TYPE_ARM_VGIC_V3   7
 
 /*
  * ioctls for VM fds
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5] ARM/KVM: save and restore generic timer registers

2013-12-13 Thread Andre Przywara
For migration to work we need to save (and later restore) the state of
each core's virtual generic timer.
Since this is per VCPU, we can use the [gs]et_one_reg ioctl and export
the three needed registers (control, counter, compare value).
Though they live in cp15 space, we don't use the existing list, since
they need special accessor functions and the arch timer is optional.

Signed-off-by: Andre Przywara andre.przyw...@linaro.org
Signed-off-by: Christoffer Dall christoffer.d...@linaro.org
---
Changes from v1:
- move code out of coproc.c and into guest.c and arch_timer.c
- present the registers with their native CP15 addresses, but without
  using space in the VCPU's cp15 array
- do the user space copying in the accessor functions

Changes from v2:
- fix compilation without CONFIG_ARCH_TIMER
- fix compilation for arm64 by defining the appropriate registers there
- move userspace access out of arch_timer.c into coproc.c
- Christoffer: removed whitespace in function declaration

Changes from v3:
- adapted Marc's SYSREG macro magic from kvmtool for nicer looking code

Changes from v4:
- remove ARM64-REG32 type, the ARM ARM defines no 32-bit system registers

 arch/arm/include/asm/kvm_host.h   |  3 ++
 arch/arm/include/uapi/asm/kvm.h   | 20 +
 arch/arm/kvm/guest.c  | 92 ++-
 arch/arm64/include/uapi/asm/kvm.h | 18 
 virt/kvm/arm/arch_timer.c | 34 +++
 5 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 8a6f6db..098f7dd 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -225,4 +225,7 @@ static inline int kvm_arch_dev_ioctl_check_extension(long 
ext)
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
+int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index c498b60..835b867 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_32_CRN_MASK0x7800
 #define KVM_REG_ARM_32_CRN_SHIFT   11
 
+#define ARM_CP15_REG_SHIFT_MASK(x,n) \
+   (((x)  KVM_REG_ARM_ ## n ## _SHIFT)  KVM_REG_ARM_ ## n ## _MASK)
+
+#define __ARM_CP15_REG(op1,crn,crm,op2) \
+   (KVM_REG_ARM | (15  KVM_REG_ARM_COPROC_SHIFT) | \
+   ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
+   ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
+   ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
+   ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
+
+#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
+
+#define __ARM_CP15_REG64(op1,crm) \
+   (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
+#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
+
+#define KVM_REG_ARM_TIMER_CTL  ARM_CP15_REG32(0, 14, 3, 1)
+#define KVM_REG_ARM_TIMER_CNT  ARM_CP15_REG64(1, 14) 
+#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14) 
+
 /* Normal registers are mapped as coprocessor 16. */
 #define KVM_REG_ARM_CORE   (0x0010  KVM_REG_ARM_COPROC_SHIFT)
 #define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 20f8d97..2786eae 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -109,6 +109,83 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
return -EINVAL;
 }
 
+#ifndef CONFIG_KVM_ARM_TIMER
+
+#define NUM_TIMER_REGS 0
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   return 0;
+}
+
+static bool is_timer_reg(u64 index)
+{
+   return false;
+}
+
+int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+{
+   return 0;
+}
+
+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
+{
+   return 0;
+}
+
+#else
+
+#define NUM_TIMER_REGS 3
+
+static bool is_timer_reg(u64 index)
+{
+   switch (index) {
+   case KVM_REG_ARM_TIMER_CTL:
+   case KVM_REG_ARM_TIMER_CNT:
+   case KVM_REG_ARM_TIMER_CVAL:
+   return true;
+   }
+   return false;
+}
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
+   return -EFAULT;
+
+   return 0;
+}
+
+#endif
+
+static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+   void __user *uaddr = (void __user *)(long)reg-addr;
+   u64 val;
+   int ret;
+
+   ret = copy_from_user(val, uaddr

Re: [PATCH v5] ARM/KVM: save and restore generic timer registers

2013-12-13 Thread Andre Przywara

On 12/13/2013 09:10 PM, Christoffer Dall wrote:

On Fri, Dec 13, 2013 at 02:23:26PM +0100, Andre Przywara wrote:

For migration to work we need to save (and later restore) the state of
each core's virtual generic timer.
Since this is per VCPU, we can use the [gs]et_one_reg ioctl and export
the three needed registers (control, counter, compare value).
Though they live in cp15 space, we don't use the existing list, since
they need special accessor functions and the arch timer is optional.

Signed-off-by: Andre Przywara andre.przyw...@linaro.org
Signed-off-by: Christoffer Dall christoffer.d...@linaro.org
---
Changes from v1:
- move code out of coproc.c and into guest.c and arch_timer.c
- present the registers with their native CP15 addresses, but without
   using space in the VCPU's cp15 array
- do the user space copying in the accessor functions

Changes from v2:
- fix compilation without CONFIG_ARCH_TIMER
- fix compilation for arm64 by defining the appropriate registers there
- move userspace access out of arch_timer.c into coproc.c
- Christoffer: removed whitespace in function declaration

Changes from v3:
- adapted Marc's SYSREG macro magic from kvmtool for nicer looking code

Changes from v4:
- remove ARM64-REG32 type, the ARM ARM defines no 32-bit system registers

  arch/arm/include/asm/kvm_host.h   |  3 ++
  arch/arm/include/uapi/asm/kvm.h   | 20 +
  arch/arm/kvm/guest.c  | 92 ++-
  arch/arm64/include/uapi/asm/kvm.h | 18 
  virt/kvm/arm/arch_timer.c | 34 +++
  5 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 8a6f6db..098f7dd 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -225,4 +225,7 @@ static inline int kvm_arch_dev_ioctl_check_extension(long 
ext)
  int kvm_perf_init(void);
  int kvm_perf_teardown(void);

+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
+int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
+
  #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index c498b60..835b867 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
  #define KVM_REG_ARM_32_CRN_MASK   0x7800
  #define KVM_REG_ARM_32_CRN_SHIFT  11

+#define ARM_CP15_REG_SHIFT_MASK(x,n) \
+   (((x)  KVM_REG_ARM_ ## n ## _SHIFT)  KVM_REG_ARM_ ## n ## _MASK)
+
+#define __ARM_CP15_REG(op1,crn,crm,op2) \
+   (KVM_REG_ARM | (15  KVM_REG_ARM_COPROC_SHIFT) | \
+   ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
+   ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
+   ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
+   ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
+
+#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
+
+#define __ARM_CP15_REG64(op1,crm) \
+   (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
+#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
+
+#define KVM_REG_ARM_TIMER_CTL  ARM_CP15_REG32(0, 14, 3, 1)
+#define KVM_REG_ARM_TIMER_CNT  ARM_CP15_REG64(1, 14)
+#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
+
  /* Normal registers are mapped as coprocessor 16. */
  #define KVM_REG_ARM_CORE  (0x0010  KVM_REG_ARM_COPROC_SHIFT)
  #define KVM_REG_ARM_CORE_REG(name)(offsetof(struct kvm_regs, name) / 4)
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 20f8d97..2786eae 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -109,6 +109,83 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
return -EINVAL;
  }

+#ifndef CONFIG_KVM_ARM_TIMER
+
+#define NUM_TIMER_REGS 0
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   return 0;
+}
+
+static bool is_timer_reg(u64 index)
+{
+   return false;
+}
+
+int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+{
+   return 0;
+}
+
+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
+{
+   return 0;
+}
+
+#else
+
+#define NUM_TIMER_REGS 3
+
+static bool is_timer_reg(u64 index)
+{
+   switch (index) {
+   case KVM_REG_ARM_TIMER_CTL:
+   case KVM_REG_ARM_TIMER_CNT:
+   case KVM_REG_ARM_TIMER_CVAL:
+   return true;
+   }
+   return false;
+}
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
+   return -EFAULT;
+
+   return 0;
+}
+
+#endif
+
+static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+   void __user *uaddr

Re: [PATCH v4] ARM/KVM: save and restore generic timer registers

2013-12-12 Thread Andre Przywara

On 12/12/2013 10:23 AM, Peter Maydell wrote:

On 12 December 2013 02:28, Christoffer Dall christoffer.d...@linaro.org wrote:

diff --git a/Documentation/virtual/kvm/api.txt 
b/Documentation/virtual/kvm/api.txt
index a30035d..9565e6a 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1889,9 +1889,12 @@ value in the kvm_regs structure seen as a 32bit array.
  arm64 CCSIDR registers are demultiplexed by CSSELR value:
0x6020  0011 00 csselr:8

-arm64 system registers have the following id bit patterns:
+arm64 64-bit system registers have the following id bit patterns:
0x6030  0013 op0:2 op1:3 crn:4 crm:4 op2:3

+arm64 32-bit system registers have the following id bit patterns:
+  0x6020  0013 op0:2 op1:3 crn:4 crm:4 op2:3


What does it mean to say that a system register for AArch64
is 32 bits given that MRS/MSR always operate on a 64 bit
register? We have the distinction in AArch32 because the
instructions (and whether the input/output is in one register
or a register pair) are different, but I can't see the need for
AArch64.


But ARMv8 ARM still defines these registers as 32-bit:
D8.5.14: CNTV_CTL_EL0
Attributes
   CNTV_CTL_EL0 is a 32-bit register.
But indeed the MSR/MRS instruction references a Xt register, and the 
documentation does not seem to tell how this is handled, so I assume 
this is zero-extended.

Would be great to have this clarified, though.

Regards,
Andre.




(The code I've just written for QEMU to handle sysregs says
they're all 64 bit...)

thanks
-- PMM



--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4] ARM/KVM: save and restore generic timer registers

2013-12-10 Thread Andre Przywara
From: Andre Przywara andre.przyw...@calxeda.com

For migration to work we need to save (and later restore) the state of
each cores virtual generic timer.
Since this is per VCPU, we can use the [gs]et_one_reg ioctl and export
the three needed registers (control, counter, compare value).
Though they live in cp15 space, we don't use the existing list, since
they need special accessor functions and the arch timer is optional.

Signed-off-by: Andre Przywara andre.przyw...@linaro.org
Signed-off-by: Christoffer Dall christoffer.d...@linaro.org
---

Changes from v1:
- move code out of coproc.c and into guest.c and arch_timer.c
- present the registers with their native CP15 addresses, but without
  using space in the VCPU's cp15 array
- do the user space copying in the accessor functions

Changes from v2:
- fix compilation without CONFIG_ARCH_TIMER
- fix compilation for arm64 by defining the appropriate registers there
- move userspace access out of arch_timer.c into coproc.c
- Christoffer: removed whitespace in function declaration

Changes from v3:
- adapted Marc's SYSREG macro magic from kvmtool for nicer looking code

 arch/arm/include/asm/kvm_host.h   |  3 ++
 arch/arm/include/uapi/asm/kvm.h   | 20 +
 arch/arm/kvm/guest.c  | 92 ++-
 arch/arm64/include/uapi/asm/kvm.h | 19 
 virt/kvm/arm/arch_timer.c | 34 +++
 5 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 8a6f6db..098f7dd 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -225,4 +225,7 @@ static inline int kvm_arch_dev_ioctl_check_extension(long 
ext)
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
+int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index c498b60..835b867 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_32_CRN_MASK0x7800
 #define KVM_REG_ARM_32_CRN_SHIFT   11
 
+#define ARM_CP15_REG_SHIFT_MASK(x,n) \
+   (((x)  KVM_REG_ARM_ ## n ## _SHIFT)  KVM_REG_ARM_ ## n ## _MASK)
+
+#define __ARM_CP15_REG(op1,crn,crm,op2) \
+   (KVM_REG_ARM | (15  KVM_REG_ARM_COPROC_SHIFT) | \
+   ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
+   ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
+   ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
+   ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
+
+#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
+
+#define __ARM_CP15_REG64(op1,crm) \
+   (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
+#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
+
+#define KVM_REG_ARM_TIMER_CTL  ARM_CP15_REG32(0, 14, 3, 1)
+#define KVM_REG_ARM_TIMER_CNT  ARM_CP15_REG64(1, 14) 
+#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14) 
+
 /* Normal registers are mapped as coprocessor 16. */
 #define KVM_REG_ARM_CORE   (0x0010  KVM_REG_ARM_COPROC_SHIFT)
 #define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 20f8d97..2786eae 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -109,6 +109,83 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
return -EINVAL;
 }
 
+#ifndef CONFIG_KVM_ARM_TIMER
+
+#define NUM_TIMER_REGS 0
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   return 0;
+}
+
+static bool is_timer_reg(u64 index)
+{
+   return false;
+}
+
+int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+{
+   return 0;
+}
+
+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
+{
+   return 0;
+}
+
+#else
+
+#define NUM_TIMER_REGS 3
+
+static bool is_timer_reg(u64 index)
+{
+   switch (index) {
+   case KVM_REG_ARM_TIMER_CTL:
+   case KVM_REG_ARM_TIMER_CNT:
+   case KVM_REG_ARM_TIMER_CVAL:
+   return true;
+   }
+   return false;
+}
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
+   return -EFAULT;
+
+   return 0;
+}
+
+#endif
+
+static int set_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+   void __user *uaddr = (void __user *)(long)reg-addr;
+   u64 val;
+   int ret;
+
+   ret = copy_from_user(val, uaddr, KVM_REG_SIZE(reg-id));
+   if (ret != 0

Re: [PATCH v4] ARM/KVM: save and restore generic timer registers

2013-12-10 Thread Andre Przywara

On 12/10/2013 11:50 AM, Andre Przywara wrote:

From: Andre Przywara andre.przyw...@calxeda.com


Ooops, I managed to screw up the authorship :-( Can the committer please 
change this to: Andre Przywara andre.przyw...@linaro.org (as in the 
signed-off-by?)


Thanks,
Andre.


For migration to work we need to save (and later restore) the state of
each cores virtual generic timer.
Since this is per VCPU, we can use the [gs]et_one_reg ioctl and export
the three needed registers (control, counter, compare value).
Though they live in cp15 space, we don't use the existing list, since
they need special accessor functions and the arch timer is optional.

Signed-off-by: Andre Przywara andre.przyw...@linaro.org
Signed-off-by: Christoffer Dall christoffer.d...@linaro.org
---

Changes from v1:
- move code out of coproc.c and into guest.c and arch_timer.c
- present the registers with their native CP15 addresses, but without
   using space in the VCPU's cp15 array
- do the user space copying in the accessor functions

Changes from v2:
- fix compilation without CONFIG_ARCH_TIMER
- fix compilation for arm64 by defining the appropriate registers there
- move userspace access out of arch_timer.c into coproc.c
- Christoffer: removed whitespace in function declaration

Changes from v3:
- adapted Marc's SYSREG macro magic from kvmtool for nicer looking code

  arch/arm/include/asm/kvm_host.h   |  3 ++
  arch/arm/include/uapi/asm/kvm.h   | 20 +
  arch/arm/kvm/guest.c  | 92 ++-
  arch/arm64/include/uapi/asm/kvm.h | 19 
  virt/kvm/arm/arch_timer.c | 34 +++
  5 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 8a6f6db..098f7dd 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -225,4 +225,7 @@ static inline int kvm_arch_dev_ioctl_check_extension(long 
ext)
  int kvm_perf_init(void);
  int kvm_perf_teardown(void);

+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid);
+int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value);
+
  #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index c498b60..835b867 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -119,6 +119,26 @@ struct kvm_arch_memory_slot {
  #define KVM_REG_ARM_32_CRN_MASK   0x7800
  #define KVM_REG_ARM_32_CRN_SHIFT  11

+#define ARM_CP15_REG_SHIFT_MASK(x,n) \
+   (((x)  KVM_REG_ARM_ ## n ## _SHIFT)  KVM_REG_ARM_ ## n ## _MASK)
+
+#define __ARM_CP15_REG(op1,crn,crm,op2) \
+   (KVM_REG_ARM | (15  KVM_REG_ARM_COPROC_SHIFT) | \
+   ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
+   ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
+   ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
+   ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
+
+#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
+
+#define __ARM_CP15_REG64(op1,crm) \
+   (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
+#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
+
+#define KVM_REG_ARM_TIMER_CTL  ARM_CP15_REG32(0, 14, 3, 1)
+#define KVM_REG_ARM_TIMER_CNT  ARM_CP15_REG64(1, 14)
+#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
+
  /* Normal registers are mapped as coprocessor 16. */
  #define KVM_REG_ARM_CORE  (0x0010  KVM_REG_ARM_COPROC_SHIFT)
  #define KVM_REG_ARM_CORE_REG(name)(offsetof(struct kvm_regs, name) / 4)
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index 20f8d97..2786eae 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -109,6 +109,83 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, 
struct kvm_regs *regs)
return -EINVAL;
  }

+#ifndef CONFIG_KVM_ARM_TIMER
+
+#define NUM_TIMER_REGS 0
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   return 0;
+}
+
+static bool is_timer_reg(u64 index)
+{
+   return false;
+}
+
+int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
+{
+   return 0;
+}
+
+u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
+{
+   return 0;
+}
+
+#else
+
+#define NUM_TIMER_REGS 3
+
+static bool is_timer_reg(u64 index)
+{
+   switch (index) {
+   case KVM_REG_ARM_TIMER_CTL:
+   case KVM_REG_ARM_TIMER_CNT:
+   case KVM_REG_ARM_TIMER_CVAL:
+   return true;
+   }
+   return false;
+}
+
+static int copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+   if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
+   return -EFAULT;
+   uindices++;
+   if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
+   return -EFAULT;
+
+   return 0;
+}
+
+#endif
+
+static int set_timer_reg(struct

Re: [RFC PATCH] Emulate MOVBE

2013-04-10 Thread Andre Przywara
On Wed, 10 Apr 2013 01:46:02 +0200
Borislav Petkov b...@alien8.de wrote:

 Hi guys,
 
 so I was trying to repro tglx's bug in smpboot.c and for some reason,
 the most reliable way to trigger it was to boot an 32-bit atom smp
 guest in kvm (don't ask :)).
 
 The problem, however, was that atom wants MOVBE and qemu doesn't
 emulate it yet (except Richard's patches which I used in order to be
 able to actually even boot a guest).
 
 However, without hw acceleration, qemu is pretty slow, and waiting for
 an smp guest to boot in sw-only emulation is not fun. So, just for
 funsies, I decided to give the MOVBE emulation a try.
 
 Patch is below, 8 core smp atom guest boots fine and in 6-ish seconds
 with it. :-)
 
 I know, I know, it still needs cleaning up and proper rFLAGS handling
 but that is for later. For now, I'd very much like to hear whether
 this approach even makes sense and if so, what should be improved.
 
 Thanks, and thanks to Andre and Jörg for their help.
 
 Not-yet-signed-off-by: Borislav Petkov b...@suse.de

You are missing an (hackish) older patch which enables the MOVBE CPUID
bit even if the host does not have it (malformed due to cp):
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -273,7 +273,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2
*entry, u32 function,
cpuid_mask(entry-ecx, 4); /* we support x2apic
emulation even if host does not support
 * it since we emulate x2apic in software */
-   entry-ecx |= F(X2APIC);
+   entry-ecx |= (F(X2APIC) | F(MOVBE));
break;
/* function 2 entries are STATEFUL. That is, repeated cpuid
commands
 * may return different values. This forces us to get_cpu()
before

 
 --
 diff --git a/arch/x86/include/asm/kvm_emulate.h
 b/arch/x86/include/asm/kvm_emulate.h index 15f960c06ff7..ae01c765cd77
 100644 --- a/arch/x86/include/asm/kvm_emulate.h
 +++ b/arch/x86/include/asm/kvm_emulate.h
 @@ -281,6 +281,7 @@ struct x86_emulate_ctxt {
  
   /* decode cache */
   u8 twobyte;
 + u8 thirdbyte;
   u8 b;
   u8 intercept;
   u8 lock_prefix;
 diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
 index a335cc6cde72..0ccff339359d 100644
 --- a/arch/x86/kvm/emulate.c
 +++ b/arch/x86/kvm/emulate.c
 @@ -152,6 +152,7 @@
  #define Avx ((u64)1  43)  /* Advanced Vector Extensions */
  #define Fastop  ((u64)1  44)  /* Use opcode::u.fastop */
  #define NoWrite ((u64)1  45)  /* No writeback */
 +#define ThreeByte   ((u64)1  46)  /* Three byte opcodes 0F 38 and
 0F 3A */ 
  #define X2(x...) x, x
  #define X3(x...) X2(x), x
 @@ -3107,6 +3108,34 @@ static int em_mov(struct x86_emulate_ctxt
 *ctxt) return X86EMUL_CONTINUE;
  }
  
 +static int em_movbe(struct x86_emulate_ctxt *ctxt)
 +{
 + char *valptr = ctxt-src.valptr;
 +
 + switch (ctxt-op_bytes) {
 + case 2:
 + *(u16 *)valptr = swab16(*(u16 *)valptr);
 + break;
 + case 4:
 + *(u32 *)valptr = swab32(*(u32 *)valptr);
 +
 + /*
 +  * clear upper dword for 32-bit operand size in
 64-bit mode.
 +  */
 + if (ctxt-mode == X86EMUL_MODE_PROT64)
 + *((u32 *)valptr + 1) = 0x0;
 + break;
 + case 8:
 + *(u64 *)valptr = swab64(*(u64 *)valptr);
 + break;
 + default:
 + return X86EMUL_PROPAGATE_FAULT;
 + }
 +
 + memcpy(ctxt-dst.valptr, ctxt-src.valptr, ctxt-op_bytes);
 + return X86EMUL_CONTINUE;
 +}
 +
On 04/09/2013 05:03 PM, Borislav Petkov wrote:
 
 Note to self: this destroys the src operand but it shouldn't. Fix it
 tomorrow.
 

What about this one?

*(u16 *)(ctxt-dst.valptr) = swab16(*(u16 *)(ctxt-src.valptr));

Respective versions for the other operand sizes, of course, and drop
the final memcpy.

  static int em_cr_write(struct x86_emulate_ctxt *ctxt)
  {
   if (ctxt-ops-set_cr(ctxt, ctxt-modrm_reg, ctxt-src.val))
 @@ -3974,7 +4003,8 @@ static const struct opcode twobyte_table[256] =
 { I(ImplicitOps | VendorSpecific, em_sysenter),
   I(ImplicitOps | Priv | VendorSpecific, em_sysexit),
   N, N,
 - N, N, N, N, N, N, N, N,
 + I(ModRM | Mov | ThreeByte | VendorSpecific, em_movbe),
 + N, N, N, N, N, N, N,

In a real world VendorSpecific should be replaced with something more
meaningful. Depends on KVMs intention to emulate instructions, actually
out of scope for a pure virtualizer.

What is the opinion from the KVM folks on this? Shall we start to
emulate instructions the host does not provide? In this particular case
a relatively simple patch fixes a problem (starting Atom optimized
kernels on non-Atom machines).

(And if one can believe the AMD Fam16h SWOG [1], PS4^Wfuture AMD
processors have MOVBE, so it's not even actually one CPU anymore).

   /* 0x40 - 0x4F */
   X16(D(DstReg | SrcMem | ModRM | Mov)),
   /* 0x50 - 0x5F */
 @@ -4323,6 +4353,15 @@ done_prefixes:
   }

Re: [RFC PATCH] Emulate MOVBE

2013-04-10 Thread Andre Przywara
On Wed, 10 Apr 2013 13:08:46 +0300
Gleb Natapov g...@redhat.com wrote:

 On Wed, Apr 10, 2013 at 11:29:42AM +0200, Andre Przywara wrote:
  In a real world VendorSpecific should be replaced with something
  more meaningful. Depends on KVMs intention to emulate instructions,
  actually out of scope for a pure virtualizer.
  
 Something like EmulateOnUD.

Right.

  What is the opinion from the KVM folks on this? Shall we start to
  emulate instructions the host does not provide? In this particular
  case a relatively simple patch fixes a problem (starting Atom
  optimized kernels on non-Atom machines).
 We can add the emulation, but we should not start announcing the
 instruction availability to a guest if host cpu does not have it by
 default. This may trick a guest into thinking that movbe is the
 fastest way to do something when it is not.

Good point. I'd also like to have a switch which enables this kind of
non-standard behavior. Actually this should be requested by QEMU,
right? So that a single guest can override the CPUID masking done by
the kernel if it really really wants to.
 
  
  (And if one can believe the AMD Fam16h SWOG [1], PS4^Wfuture AMD
  processors have MOVBE, so it's not even actually one CPU anymore).
 If a host CPU has the instruction emulation is not needed unless the
 instruction is used for MMIO access.

I meant to emulate such a CPU. -cpu ps4 ;-)

Regards,
Andre.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Semantics of -cpu host (was Re: [Qemu-devel] [PATCH 2/2] Expose tsc deadline timer cpuid to guest)

2012-05-09 Thread Andre Przywara

On 05/07/2012 08:21 PM, Eduardo Habkost wrote:


Andre? Are you able to help to answer the question below?


Sorry for the delay, the easy answers first:


I would like to clarify what's the expected behavior of -cpu host to
be able to continue working on it.


The purpose of -cpu host is to let guests use ISA features that the host 
CPU provides. Those would not need any KVM/QEMU intervention, because 
they work out of the box. Things like AES or SSE4.2, which are used by 
Linux and glibc, for instance. Users would expect those to be usable, 
and actually we only need to set the bits and are done.


A second goal is to get rid of the awkward and artificial 
family/model/stepping settings and just let the guest see the actual CPU 
model. This has some strings attached, though, but other virtualization 
solution do it the same way and they can cope with it.


A third thing currently not really addressed are the more informational 
bits like cache size and organization and TLB layout. Those are 
properties of the (core) CPU (except shared L3, cache maybe) and apply 
to guests as well. I don't see any reason why this should not be exposed 
to the guest. From the top of my head I don't know any prominent user 
(just glibc reading the cache size, but not really using it), but I 
guess there are applications which benefit from it.


What clearly is not the intention of -cpu host is to provide access to 
every feature a certain CPU model provides. So things which require 
emulation or hypervisor intervention are not in the primary use case. 
That does not mean that they don't need to implemented, but that was not 
the purpose of -cpu host and they should be handled independently.


Regards,
Andre.

I believe the code will need to be

fixed on either case, but first we need to figure out what are the
expectations/requirements, to know _which_ changes will be needed.


On Tue, Apr 24, 2012 at 02:19:25PM -0300, Eduardo Habkost wrote:

(CCing Andre Przywara, in case he can help to clarify what's the
expected meaning of -cpu host)


[...]

I am not sure I understand what you are proposing. Let me explain the
use case I am thinking about:

- Feature FOO is of type (A) (e.g. just a new instruction set that
   doesn't require additional userspace support)
- User has a Qemu vesion that doesn't know anything about feature FOO
- User gets a new CPU that supports feature FOO
- User gets a new kernel that supports feature FOO (i.e. has FOO in
   GET_SUPPORTED_CPUID)
- User does _not_ upgrade Qemu.
- User expects to get feature FOO enabled if using -cpu host, without
   upgrading Qemu.

The problem here is: to support the above use-case, userspace need a
probing mechanism that can differentiate _new_ (previously unknown)
features that are in group (A) (safe to blindly enable) from features
that are in group (B) (that can't be enabled without an userspace
upgrade).

In short, it becomes a problem if we consider the following case:

- Feature BAR is of type (B) (it can't be enabled without extra
   userspace support)
- User has a Qemu version that doesn't know anything about feature BAR
- User gets a new CPU that supports feature BAR
- User gets a new kernel that supports feature BAR (i.e. has BAR in
   GET_SUPPORTED_CPUID)
- User does _not_ upgrade Qemu.
- User simply shouldn't get feature BAR enabled, even if using -cpu
   host, otherwise Qemu would break.

If userspace always limited itself to features it knows about, it would
be really easy to implement the feature without any new probing
mechanism from the kernel. But that's not how I think users expect -cpu
host to work. Maybe I am wrong, I don't know. I am CCing Andre, who
introduced the -cpu host feature, in case he can explain what's the
expected semantics on the cases above.






--
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: AMD SVM specification

2012-02-27 Thread Andre Przywara

On 02/27/2012 11:09 AM, Prateek Sharma wrote:

Hello,
  I know this is not the right forum for this, but i am looking for
the recent specification/documentation of the AMD NPT and SVM
features. All i can find is the old pacifica document dating back to
2005, and only the NPT whitepaper.


The technical SVM documentation is in the AMD64 Architecture 
Programmer's Manual (APM) Volume 2:

http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf

SVM is detailed in chapter 15, with appendix B  C containing the needed 
bits for the data structures. Other chapters in this document contain 
details about paging, though this is mostly not AMD specific.


Regards,
Andre.


 The reason i seek this documentation is that i wish to modify some
KVM code. Specifically, i am interested in how the hardware
sets/resets the accessed/dirty bits of the guest/nested tables
[https://lkml.org/lkml/2011/6/22/20]

Any help will be appreciated.

Prateek



--
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: OpenBSD 5.0 kernel panic in AMD K10 cpu power state

2011-11-10 Thread Andre Przywara

On 11/10/2011 09:46 AM, Avi Kivity wrote:

(re-adding cc)


On 11/09/2011 09:35 PM, Walter Haidinger wrote:

Am 09.11.2011 14:40, schrieb Avi Kivity:

Actually, it looks like an OpenBSD bug.  According to the AMD
documentation:


Well, the OpenBSD developers are very confident that is
a bug in the KVM cpu emulation and _not_ in OpenBSD.

Basically they say that [despite -cpu host], the emulated
cpu does not look like a real, but _non-existant_ cpu.
Virtualization should look like _existing_ hardware.


That is true.  But OpenBSD is not following the vendor's recommendation
for how software should access the hardware.


Since the list archive at
http://marc.info/?l=openbsd-miscm=132077741910464w=2
lags a bit, I'm attaching some parts of the thread below:

However, please remember it's OpenBSD, so the tone is, let's just
say, rough.


Less than expected, actually.


The panic you hit is for an msr read, not a write. I'm aware those
registers are read-only. The CPUID check isn't done, it matches on
all family 10 and/or higher AMD processors. They're pretending to be
  an AMD K10 processor. On all real hardware I've tested this works
fine. If you wish to be pedantic, patches are welcome.


Avi, thanks for caring of that.

The manual is clear here: no CPUID bit, no MSRs. Beside that the 
emulated ACPI tables probably also don't provide any info here, right?
The fact that it runs: on all family 10 and/or higher AMD processors 
is just an empiric observation, not a law. You would be astonished what 
can be fused off...


We had a similar discussion here with unconditional AMD Northbridge PCI 
accesses when detecting certain AMD CPU family/model/steppings in the 
Linux kernel already (...but every AMD CPU has a northbridge...)
We (as virtualization guys) should not step back so easily here, 
especially if the spec is so clear. That spec argument should actually 
appeal to the OpenBSD guys, too. I got the impression that their design 
is, well, actually well designed.




So they're actually open to adding the cpuid check.


They sent me a patch as a workaround, which:


The previous patch avoids touching the msr at all if ACPI indicates
speed scaling is unavailable, this should prevent your panic.


with -cpu host, OpenBSD dmesg showed the 1100T:

cpu0: AMD Phenom(tm) II X6 1100T Processor (AuthenticAMD 686-class, 512KB L2 
cache) 3.31 GHz cpu0:
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,CX16,POPCNT
...
bios0: vendor Bochs version Bochs date 01/01/2007 bios0: Bochs
Bochs

They shouldn't be pretending to be AMD, especially if that emulation
is very incompatible.


but the bug is in the Linux KVM:


They're pretending to be an AMD K10 processor.


Exactly.  What they are doing is wrong. They are pretending to be a
AMD K10 processor _badly_, and then they think they can say oh, but
you need to check all these other registers too. A machine with that
setup has never physically existed.


Is this all because I used -cpu host?



-cpu host is not to blame, you could get the same result from other
combinations of cpu model and family.

I'll look at adding support for this MSR; should be simple.  But in
general processor features need to be qualified by cpuid, not by model.


I guess emulating part of P-states will open up a can of worms. Beside 
the generic MSRs (0xC001006[1-3]) there are actual family specific ones 
which are selected by the CPUID family. So you would end up emulating 
them, too. I have a hard time to think about a strategy how to emulate 
this in general. So unless there is a real framework for dealing with 
P-state hints from the guest OS, I'd be reluctant with quick and dirty 
emulations.


Thanks,
Andre.

--
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


unconditional CPUID propagation?

2011-08-03 Thread Andre Przywara

Hi,

while looking through the code I found commit
f79116867ec80ed5d1d10043a3fd9ac8afd182c1 (upstream QEMU: enable SMEP) 
which unconditionally propagates the bits from CPUID leaf 0x7 to the 
guest. Though there is the KVM module in the line, this currently 
whitelists three feature bits.
Doesn't that break migration? The result of the CPUID instruction the 
guess issues only depends on the host and the KVM module's policy, not 
on the CPU model QEMU uses. So I guess migrating from a newer CPU to an 
older one breaks despite a rather conservative CPU model has been chosen 
intentionally by the user.

The same is probably true for the VIA CPUID leaf.

Is that considered OK now or is that a bug? Shall the new feature bits 
be made known to QEMU like the other ones on only enabled explicitly 
(+smep) or by -cpu host?

I can make a patch for that if that is the right way to address this.

Regards,
Andre.

--
Andre Przywara
AMD-OSRC (Dresden)
Tel: x29712


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] KVM: fix XSAVE bit scanning (now properly)

2011-06-10 Thread Andre Przywara
commit 123108f1c1aafd51d6a5c79cc04d7999dd88a930 tried to fix KVMs
XSAVE valid feature scanning, but it was wrong. It was not considering
the sparse nature of this bitfield, instead reading values from
uninitialized members of the entries array.
This patch now separates subleaf indicies from KVM's array indicies
and fills the entry before querying it's value.
This fixes AVX support in KVM guests.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/x86.c |9 +
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 694538a..2a52e69 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2418,16 +2418,17 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 
*entry, u32 function,
break;
}
case 0xd: {
-   int i;
+   int idx, i;
 
entry-flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-   for (i = 1; *nent  maxnent  i  64; ++i) {
-   if (entry[i].eax == 0 || !supported_xcr0_bit(i))
+   for (idx = 1, i = 1; *nent  maxnent  idx  64; ++idx) {
+   do_cpuid_1_ent(entry[i], function, idx);
+   if (entry[i].eax == 0 || !supported_xcr0_bit(idx))
continue;
-   do_cpuid_1_ent(entry[i], function, i);
entry[i].flags |=
   KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
++*nent;
+   ++i;
}
break;
}
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] QEMU: Fix KVM XSAVE feature bit enumeration

2011-06-10 Thread Andre Przywara
When iterating through the XSAVE feature enumeration CPUID leaf (0xD)
we should not stop at the first zero EAX, but instead keep scanning
since there are gaps in the enumeration (ECX=1 for instance).
This fixes the proper usage of AVX in KVM guests.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 target-i386/kvm.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index faedc6c..4a97f78 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -448,6 +448,8 @@ int kvm_arch_init_vcpu(CPUState *env)
 case 0xb:
 case 0xd:
 for (j = 0; ; j++) {
+if (i == 0xd  j == 64)
+break;
 c-function = i;
 c-flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
 c-index = j;
@@ -460,7 +462,7 @@ int kvm_arch_init_vcpu(CPUState *env)
 break;
 }
 if (i == 0xd  c-eax == 0) {
-break;
+continue;
 }
 c = cpuid_data.entries[cpuid_i++];
 }
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] KVM: Fix XSAVE feature bit enumeration

2011-06-10 Thread Andre Przywara
When iterating through the XSAVE feature enumeration CPUID leaf (0xD)
we should not stop at the first zero EAX, but instead keep scanning
since there are gaps in the enumeration (ECX=1 for instance).
This fixes the proper usage of AVX in KVM guests.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 target-i386/kvm.c |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index faedc6c..37a972f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -448,6 +448,9 @@ int kvm_arch_init_vcpu(CPUState *env)
 case 0xb:
 case 0xd:
 for (j = 0; ; j++) {
+if (i == 0xd  j == 64) {
+break;
+}
 c-function = i;
 c-flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
 c-index = j;
@@ -460,7 +463,7 @@ int kvm_arch_init_vcpu(CPUState *env)
 break;
 }
 if (i == 0xd  c-eax == 0) {
-break;
+continue;
 }
 c = cpuid_data.entries[cpuid_i++];
 }
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] kvm/x86: remove unneeded substitute search for missing CPUID entries

2011-03-31 Thread Andre Przywara

Avi Kivity wrote:

On 03/30/2011 03:01 PM, Andre Przywara wrote:

If KVM cannot find an exact match for a requested CPUID leaf, the
code will try to find the closest match instead of simply confessing
it's failure. The heuristic is on one hand wrong nowadays,
since it does not take the KVM CPUID leaves (0x40xx) into
account. On the other hand the callers of this function can all deal
with the no-match situation. So lets remove this code, as it serves
no purpose.
This fixes a crash of newer Linux kernels as KVM guests on
AMD Bulldozer CPUs, where bogus values were returned in response to
a CPUID intercept.


@@ -4959,12 +4959,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct 
kvm_vcpu *vcpu,
best = e;
break;
}
-   /*
-* Both basic or both extended?
-*/
-   if (((e-function ^ function)  0x8000) == 0)
-   if (!best || e-function  best-function)
-   best = e;
}
return best;
  }



This behaviour is mandated by the spec (looking at the Intel one), 
though it is implemented incorrectly - should always return largest 
basic leaf, and ignore the kvm leaves.


But the spec says that this applies only if EAX is higher than the 
largest supported leaf. The code as is checks whether KVM has an entry 
in the cpuid cache for it, which is not the same. Especially this case 
that hit me was a missing index entry, which should return 0.
The check for too large leaf numbers should be moved into 
kvm_emulate_cpuid(). There is already some code in QEMU (cpu_x86_cpuid) 
to handle this, but that path does not apply to KVM.


I will make a new version of this patch which replaces the old check 
with a sane version in kvm_emulate_cpuid().


Thanks for pointing this out.



I think the correct behaviour is:

if (e-function  1  (!best || e-function  best-function))
 best = e;

We probably need a find_exact_cpuid_entry() that returns NULL if it 
doesn't find a match, for internal use.


As mentioned, this behavior only applies to the actual intercept case, 
not to all users of kvm_find_cpuid_entry(). So I'd like to make this 
check in the intercept code path and not in this function.


Regards,
Andre.

--
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] kvm/x86: move and fix substitue search for missing CPUID entries

2011-03-31 Thread Andre Przywara
If KVM cannot find an exact match for a requested CPUID leaf, the
code will try to find the closest match instead of simply confessing
it's failure.
The implementation was meant to satisfy the CPUID specification, but
did not properly check for extended and standard leaves and also
didn't account for the index subleaf.
Beside that this rule only applies to CPUID intercepts, which is not
the only user of the kvm_find_cpuid_entry() function.

So fix this algorithm and move it into kvm_emulate_cpuid().
This fixes a crash of newer Linux kernels as KVM guests on
AMD Bulldozer CPUs, where bogus values were returned in response to
a CPUID intercept.

CC: sta...@kernel.org [2.6.38]
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/x86.c |   19 +--
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6e86cec..552b8f8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4959,12 +4959,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct 
kvm_vcpu *vcpu,
best = e;
break;
}
-   /*
-* Both basic or both extended?
-*/
-   if (((e-function ^ function)  0x8000) == 0)
-   if (!best || e-function  best-function)
-   best = e;
}
return best;
 }
@@ -4996,6 +4990,19 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
best = kvm_find_cpuid_entry(vcpu, function, index);
+
+   /* if no match is found, check whether we exceed the vCPU's limit
+* and return the content of the highest valid standard leaf instead.
+* This is to satisfy the CPUID specification.
+*/
+   if (!best) {
+   best = kvm_find_cpuid_entry(vcpu, function  0x8000, 0);
+   if (best  best-eax  function)
+   best = kvm_find_cpuid_entry(vcpu, best-eax, index);
+   else
+   best = NULL;
+   }
+
if (best) {
kvm_register_write(vcpu, VCPU_REGS_RAX, best-eax);
kvm_register_write(vcpu, VCPU_REGS_RBX, best-ebx);
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] kvm/x86: move and fix substitue search for missing CPUID entries

2011-03-31 Thread Andre Przywara

Avi Kivity wrote:

On 03/31/2011 03:13 PM, Andre Przywara wrote:

If KVM cannot find an exact match for a requested CPUID leaf, the
code will try to find the closest match instead of simply confessing
it's failure.
The implementation was meant to satisfy the CPUID specification, but
did not properly check for extended and standard leaves and also
didn't account for the index subleaf.
Beside that this rule only applies to CPUID intercepts, which is not
the only user of the kvm_find_cpuid_entry() function.

So fix this algorithm and move it into kvm_emulate_cpuid().
This fixes a crash of newer Linux kernels as KVM guests on
AMD Bulldozer CPUs, where bogus values were returned in response to
a CPUID intercept.

@@ -4996,6 +4990,19 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
best = kvm_find_cpuid_entry(vcpu, function, index);
+
+   /* if no match is found, check whether we exceed the vCPU's limit
+* and return the content of the highest valid standard leaf instead.
+* This is to satisfy the CPUID specification.
+*/
+   if (!best) {
+   best = kvm_find_cpuid_entry(vcpu, function  0x8000, 0);


highest valid standard leaf means the second argument should be zero, no?


Weird, but somehow true. I fixed this is in a another version (following).

Thanks for spotting this.

Andre.




+   if (best  best-eax  function)
+   best = kvm_find_cpuid_entry(vcpu, best-eax, index);
+   else
+   best = NULL;
+   }
+
if (best) {
kvm_register_write(vcpu, VCPU_REGS_RAX, best-eax);
kvm_register_write(vcpu, VCPU_REGS_RBX, best-ebx);





--
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2 v3] kvm/x86: move and fix substitue search for missing CPUID entries

2011-03-31 Thread Andre Przywara
If KVM cannot find an exact match for a requested CPUID leaf, the
code will try to find the closest match instead of simply confessing
it's failure.
The implementation was meant to satisfy the CPUID specification, but
did not properly check for extended and standard leaves and also
didn't account for the index subleaf.
Beside that this rule only applies to CPUID intercepts, which is not
the only user of the kvm_find_cpuid_entry() function.

So fix this algorithm and call it from kvm_emulate_cpuid().
This fixes a crash of newer Linux kernels as KVM guests on
AMD Bulldozer CPUs, where bogus values were returned in response to
a CPUID intercept.

CC: sta...@kernel.org [2.6.38]
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/x86.c |   31 +--
 1 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6e86cec..a38fb9b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4959,12 +4959,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct 
kvm_vcpu *vcpu,
best = e;
break;
}
-   /*
-* Both basic or both extended?
-*/
-   if (((e-function ^ function)  0x8000) == 0)
-   if (!best || e-function  best-function)
-   best = e;
}
return best;
 }
@@ -4984,6 +4978,27 @@ not_found:
return 36;
 }
 
+/*
+ * If no match is found, check whether we exceed the vCPU's limit
+ * and return the content of the highest valid _standard_ leaf instead.
+ * This is to satisfy the CPUID specification.
+ */
+static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu,
+  u32 function, u32 index)
+{
+   struct kvm_cpuid_entry2 *maxlevel;
+
+   maxlevel = kvm_find_cpuid_entry(vcpu, function  0x8000, 0);
+   if (!maxlevel || maxlevel-eax = function)
+   return NULL;
+   if (function  0x8000) {
+   maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0);
+   if (!maxlevel)
+   return NULL;
+   }
+   return kvm_find_cpuid_entry(vcpu, maxlevel-eax, index);
+}
+
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 {
u32 function, index;
@@ -4996,6 +5011,10 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
best = kvm_find_cpuid_entry(vcpu, function, index);
+
+   if (!best)
+   best = check_cpuid_limit(vcpu, function, index);
+
if (best) {
kvm_register_write(vcpu, VCPU_REGS_RAX, best-eax);
kvm_register_write(vcpu, VCPU_REGS_RBX, best-ebx);
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] kvm/x86: fix XSAVE bit scanning

2011-03-30 Thread Andre Przywara
When KVM scans the 0xD CPUID leaf for propagating the XSAVE save area
leaves, it assumes that the leaves are contigious and stops at the
first zero one. On AMD hardware there is a gap, though, as LWP uses
leaf 62 to announce it's state save area.
So lets iterate through all 64 possible leaves and simply skip zero
ones to also cover later features.

CC: sta...@kernel.org [2.6.38]
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/x86.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bfd7763..6e86cec 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2395,9 +2395,9 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, 
u32 function,
int i;
 
entry-flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-   for (i = 1; *nent  maxnent; ++i) {
-   if (entry[i - 1].eax == 0  i != 2)
-   break;
+   for (i = 1; *nent  maxnent  i  64; ++i) {
+   if (entry[i].eax == 0)
+   continue;
do_cpuid_1_ent(entry[i], function, i);
entry[i].flags |=
   KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] kvm/x86: remove unneeded substitute search for missing CPUID entries

2011-03-30 Thread Andre Przywara
If KVM cannot find an exact match for a requested CPUID leaf, the
code will try to find the closest match instead of simply confessing
it's failure. The heuristic is on one hand wrong nowadays,
since it does not take the KVM CPUID leaves (0x40xx) into
account. On the other hand the callers of this function can all deal
with the no-match situation. So lets remove this code, as it serves
no purpose.
This fixes a crash of newer Linux kernels as KVM guests on
AMD Bulldozer CPUs, where bogus values were returned in response to
a CPUID intercept.

CC: sta...@kernel.org [2.6.38]
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/x86.c |6 --
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6e86cec..625143f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4959,12 +4959,6 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct 
kvm_vcpu *vcpu,
best = e;
break;
}
-   /*
-* Both basic or both extended?
-*/
-   if (((e-function ^ function)  0x8000) == 0)
-   if (!best || e-function  best-function)
-   best = e;
}
return best;
 }
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] kvm/svm: fix DR interception handling on upcoming AMD CPUs

2011-02-09 Thread Andre Przywara

Roedel, Joerg wrote:

On Tue, Feb 08, 2011 at 07:22:29PM -0500, Andre Przywara wrote:

Somehow the code line advancing the RIP and checking for exceptions
got dropped between the post on the ML and the commit.
Add it again to let guests boot on upcoming AMD CPUs again.

Reported-by: Joerg Roedel joerg.roe...@amd.com
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/svm.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 25bd1bc..be06e58 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2776,6 +2776,7 @@ static int dr_interception(struct vcpu_svm *svm)
if (!err)
kvm_register_write(svm-vcpu, reg, val);
}
+   kvm_complete_insn_gp(svm-vcpu, err);


Any exception check takes presedence over the intercept. So a call to
skip_emulated_instruction should be sufficient here.
You are right, but I think this way the implementation is cleaner and 
more generic. If there is no exception condition detected (err==0), then 
the call will just do skip_emulated_instruction anyway.
But as I write this, I see that err is not initialized, so I'd propose 
this corrected version of the patch instead.


Regards,
Andre.

--

From 8c1dced7b4f80e4968b03656aee2452535b2ef2f Mon Sep 17 00:00:00 2001
From: Andre Przywara andre.przyw...@amd.com
Date: Wed, 9 Feb 2011 01:10:45 +0100
Subject: [PATCH] kvm/svm: fix DR interception handling on upcoming AMD CPUs

Somehow the code line advancing the RIP and checking for exceptions
got dropped between the mail on the ML and the commit.
Add it again to let guests boot on upcoming AMD CPUs again.
While at it, properly initialize the err variable to fix the write DR
case.

Reported-by: Joerg Roedel joerg.roe...@amd.com
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/svm.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 25bd1bc..d558121 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2760,7 +2760,7 @@ static int dr_interception(struct vcpu_svm *svm)
 {
int reg, dr;
unsigned long val;
-   int err;
+   int err = 0;

if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS))
return emulate_on_interception(svm);
@@ -2776,6 +2776,7 @@ static int dr_interception(struct vcpu_svm *svm)
if (!err)
kvm_register_write(svm-vcpu, reg, val);
}
+   kvm_complete_insn_gp(svm-vcpu, err);

return 1;
 }
--
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] kvm/svm: fix DR interception handling on upcoming AMD CPUs

2011-02-08 Thread Andre Przywara
Somehow the code line advancing the RIP and checking for exceptions
got dropped between the post on the ML and the commit.
Add it again to let guests boot on upcoming AMD CPUs again.

Reported-by: Joerg Roedel joerg.roe...@amd.com
Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/svm.c |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 25bd1bc..be06e58 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2776,6 +2776,7 @@ static int dr_interception(struct vcpu_svm *svm)
if (!err)
kvm_register_write(svm-vcpu, reg, val);
}
+   kvm_complete_insn_gp(svm-vcpu, err);
 
return 1;
 }
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH -v3 0/8] kvm/svm: implement new DecodeAssist features

2010-12-21 Thread Andre Przywara
Hi,

this is version 3 of the DecodeAssist patches.
I added 3 clean up patches which are not SVM specific.
Changes between v2 and v3:
- now includes the (unchanged) CR8 handling fix
- move complete_insn_gp() helper function into x86.c
- remove unnecessary comment
- fix handling of illegal CR accesses (inject #UD, should actually not occur)
- completely rework the instruction bytes copy patch
  Now this propagates the addr/len pair from the interception handling
  into the emulator. For this I cleaned up this code path a bit
  (patch 3), so it does not blow up all current users of emulate_instruction.

Changes between v1 and v2:
- goes on top of the CR8 handling fix I sent out earlier this week
  (required for proper handling of CR8 exceptions)
- handles exception cases properly (for mov cr and mov dr)
- uses X86_FEATURE_ names instead of SVM_FEATURE names (for boot_cpu_has)
  (thanks to Joerg for spotting this)
- use static_cpu_has where appropriate
- some minor code cleanups (for instance cr register calculation)
- move prefetch callback into x86_decode_insn and out of every fetch
  I refrained from ditching the callback at all, as I dont like extending
  every emulate_instruction call with NULL, 0. But if this is
  desperately needed, I can still change it.
- rename vendor specific prefetch function names

Upcoming AMD CPUs will have a SVM enhancement called DecodeAssist
which will provide more information when intercepting certain events.
These information allows to skip the instruction fetching and
decoding and handle the intercept immediately.
This patch set implements all the features which are documented
in the recent AMD manual (APM vol. 2). For details see the patches.

Please review and apply.

Regards,
Andre.


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] kvm/svm: enhance mov DR intercept handler

2010-12-21 Thread Andre Przywara
Newer SVM implementations provide the GPR number in the VMCB, so
that the emulation path is no longer necesarry to handle debug
register access intercepts. Implement the handling in svm.c and
use it when the info is provided.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/svm.c |   57 +--
 1 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index b47e2e6..eb662da 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2745,6 +2745,31 @@ static int cr0_write_interception(struct vcpu_svm *svm)
return r;
 }
 
+static int dr_interception(struct vcpu_svm *svm)
+{
+   int reg, dr;
+   unsigned long val;
+   int err;
+
+   if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS))
+   return emulate_on_interception(svm);
+
+   reg = svm-vmcb-control.exit_info_1  SVM_EXITINFO_REG_MASK;
+   dr = svm-vmcb-control.exit_code - SVM_EXIT_READ_DR0;
+
+   if (dr = 16) { /* mov to DRn */
+   val = kvm_register_read(svm-vcpu, reg);
+   err = kvm_set_dr(svm-vcpu, dr - 16, val);
+   } else {
+   err = kvm_get_dr(svm-vcpu, dr, val);
+   if (!err)
+   kvm_register_write(svm-vcpu, reg, val);
+   }
+   kvm_complete_insn_gp(svm-vcpu, err);
+
+   return 1;
+}
+
 static int cr8_write_interception(struct vcpu_svm *svm)
 {
struct kvm_run *kvm_run = svm-vcpu.run;
@@ -3010,22 +3035,22 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) 
= {
[SVM_EXIT_WRITE_CR3]= cr_interception,
[SVM_EXIT_WRITE_CR4]= cr_interception,
[SVM_EXIT_WRITE_CR8]= cr8_write_interception,
-   [SVM_EXIT_READ_DR0] = emulate_on_interception,
-   [SVM_EXIT_READ_DR1] = emulate_on_interception,
-   [SVM_EXIT_READ_DR2] = emulate_on_interception,
-   [SVM_EXIT_READ_DR3] = emulate_on_interception,
-   [SVM_EXIT_READ_DR4] = emulate_on_interception,
-   [SVM_EXIT_READ_DR5] = emulate_on_interception,
-   [SVM_EXIT_READ_DR6] = emulate_on_interception,
-   [SVM_EXIT_READ_DR7] = emulate_on_interception,
-   [SVM_EXIT_WRITE_DR0]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR1]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR2]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR3]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR4]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR5]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR6]= emulate_on_interception,
-   [SVM_EXIT_WRITE_DR7]= emulate_on_interception,
+   [SVM_EXIT_READ_DR0] = dr_interception,
+   [SVM_EXIT_READ_DR1] = dr_interception,
+   [SVM_EXIT_READ_DR2] = dr_interception,
+   [SVM_EXIT_READ_DR3] = dr_interception,
+   [SVM_EXIT_READ_DR4] = dr_interception,
+   [SVM_EXIT_READ_DR5] = dr_interception,
+   [SVM_EXIT_READ_DR6] = dr_interception,
+   [SVM_EXIT_READ_DR7] = dr_interception,
+   [SVM_EXIT_WRITE_DR0]= dr_interception,
+   [SVM_EXIT_WRITE_DR1]= dr_interception,
+   [SVM_EXIT_WRITE_DR2]= dr_interception,
+   [SVM_EXIT_WRITE_DR3]= dr_interception,
+   [SVM_EXIT_WRITE_DR4]= dr_interception,
+   [SVM_EXIT_WRITE_DR5]= dr_interception,
+   [SVM_EXIT_WRITE_DR6]= dr_interception,
+   [SVM_EXIT_WRITE_DR7]= dr_interception,
[SVM_EXIT_EXCP_BASE + DB_VECTOR]= db_interception,
[SVM_EXIT_EXCP_BASE + BP_VECTOR]= bp_interception,
[SVM_EXIT_EXCP_BASE + UD_VECTOR]= ud_interception,
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/8] kvm/svm: add new SVM feature bit names

2010-12-21 Thread Andre Przywara
the recent APM Vol.2 and the recent AMD CPUID specification describe
new CPUID features bits for SVM. Name them here for later usage.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/svm.c |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index d49d73c..e2ea75f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -51,6 +51,10 @@ MODULE_LICENSE(GPL);
 #define SVM_FEATURE_LBRV   (1   1)
 #define SVM_FEATURE_SVML   (1   2)
 #define SVM_FEATURE_NRIP   (1   3)
+#define SVM_FEATURE_TSC_RATE   (1   4)
+#define SVM_FEATURE_VMCB_CLEAN (1   5)
+#define SVM_FEATURE_FLUSH_ASID (1   6)
+#define SVM_FEATURE_DECODE_ASSIST  (1   7)
 #define SVM_FEATURE_PAUSE_FILTER   (1  10)
 
 #define NESTED_EXIT_HOST   0   /* Exit handled on host level */
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] kvm/svm: copy instruction bytes from VMCB

2010-12-21 Thread Andre Przywara
In case of a nested page fault or an intercepted #PF newer SVM
implementations provide a copy of the faulting instruction bytes
in the VMCB.
Use these bytes to feed the instruction emulator and avoid the costly
guest instruction fetch in this case.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/include/asm/kvm_emulate.h |2 +-
 arch/x86/include/asm/kvm_host.h|9 +
 arch/x86/include/asm/svm.h |4 +++-
 arch/x86/kvm/emulate.c |7 +--
 arch/x86/kvm/mmu.c |5 +++--
 arch/x86/kvm/svm.c |4 +++-
 arch/x86/kvm/vmx.c |4 ++--
 arch/x86/kvm/x86.c |6 --
 8 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h 
b/arch/x86/include/asm/kvm_emulate.h
index bf70ece..8e37deb 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -265,7 +265,7 @@ struct x86_emulate_ctxt {
 #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
 #endif
 
-int x86_decode_insn(struct x86_emulate_ctxt *ctxt);
+int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len);
 #define EMULATION_FAILED -1
 #define EMULATION_OK 0
 #define EMULATION_RESTART 1
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index de00b60..6268f6c 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -634,13 +634,13 @@ enum emulation_result {
 #define EMULTYPE_NO_DECODE (1  0)
 #define EMULTYPE_TRAP_UD   (1  1)
 #define EMULTYPE_SKIP  (1  2)
-int x86_emulate_instruction(struct kvm_vcpu *vcpu,
-   unsigned long cr2, int emulation_type);
+int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
+   int emulation_type, void *insn, int insn_len);
 
 static inline int emulate_instruction(struct kvm_vcpu *vcpu,
int emulation_type)
 {
-   return x86_emulate_instruction(vcpu, 0, emulation_type);
+   return x86_emulate_instruction(vcpu, 0, emulation_type, NULL, 0);
 }
 
 void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
@@ -721,7 +721,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
 int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code);
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code,
+  void *insn, int insn_len);
 void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
 
 void kvm_enable_tdp(void);
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index f0ffb81..f2b83bc 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -83,7 +83,9 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
u32 clean;
u32 reserved_5;
u64 next_rip;
-   u8 reserved_6[816];
+   u8 insn_len;
+   u8 insn_bytes[15];
+   u8 reserved_6[800];
 };
 
 
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 6366735..02a0041 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2610,7 +2610,7 @@ done:
 }
 
 int
-x86_decode_insn(struct x86_emulate_ctxt *ctxt)
+x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
 {
struct x86_emulate_ops *ops = ctxt-ops;
struct decode_cache *c = ctxt-decode;
@@ -2621,7 +2621,10 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt)
struct operand memop = { .type = OP_NONE };
 
c-eip = ctxt-eip;
-   c-fetch.start = c-fetch.end = c-eip;
+   c-fetch.start = c-eip;
+   c-fetch.end = c-fetch.start + insn_len;
+   if (insn_len  0)
+   memcpy(c-fetch.data, insn, insn_len);
ctxt-cs_base = seg_base(ctxt, ops, VCPU_SREG_CS);
 
switch (mode) {
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 75334de..397a98f 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3329,7 +3329,8 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
}
 }
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code)
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
+  void *insn, int insn_len)
 {
int r;
enum emulation_result er;
@@ -3347,7 +3348,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, 
u32 error_code)
if (r)
goto out;
 
-   er = x86_emulate_instruction(vcpu, cr2, 0);
+   er = x86_emulate_instruction(vcpu, cr2, 0, insn, insn_len);
 
switch (er) {
case EMULATE_DONE:
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 7871702..00a6117 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1527,7 +1527,9 @@ static int pf_interception(struct vcpu_svm *svm)
trace_kvm_page_fault(fault_address, error_code);
if (!npt_enabled

[PATCH 2/8] kvm: move complete_insn_gp() into x86.c

2010-12-21 Thread Andre Przywara
move the complete_insn_gp() helper function out of the VMX part
into the generic x86 part to make it usable by SVM.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/include/asm/kvm_host.h |2 ++
 arch/x86/kvm/vmx.c  |   16 
 arch/x86/kvm/x86.c  |9 +
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index cb5cad2..cd4a990 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -828,4 +828,6 @@ void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
 bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu);
 extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 
+void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
+
 #endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 8e87bae..fd8ffde 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3147,14 +3147,6 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char 
*hypercall)
hypercall[2] = 0xc1;
 }
 
-static void complete_insn_gp(struct kvm_vcpu *vcpu, int err)
-{
-   if (err)
-   kvm_inject_gp(vcpu, 0);
-   else
-   skip_emulated_instruction(vcpu);
-}
-
 static int handle_cr(struct kvm_vcpu *vcpu)
 {
unsigned long exit_qualification, val;
@@ -3172,21 +3164,21 @@ static int handle_cr(struct kvm_vcpu *vcpu)
switch (cr) {
case 0:
err = kvm_set_cr0(vcpu, val);
-   complete_insn_gp(vcpu, err);
+   kvm_complete_insn_gp(vcpu, err);
return 1;
case 3:
err = kvm_set_cr3(vcpu, val);
-   complete_insn_gp(vcpu, err);
+   kvm_complete_insn_gp(vcpu, err);
return 1;
case 4:
err = kvm_set_cr4(vcpu, val);
-   complete_insn_gp(vcpu, err);
+   kvm_complete_insn_gp(vcpu, err);
return 1;
case 8: {
u8 cr8_prev = kvm_get_cr8(vcpu);
u8 cr8 = kvm_register_read(vcpu, reg);
err = kvm_set_cr8(vcpu, cr8);
-   complete_insn_gp(vcpu, err);
+   kvm_complete_insn_gp(vcpu, err);
if (irqchip_in_kernel(vcpu-kvm))
return 1;
if (cr8_prev = cr8)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2dbf68c..1d54cb7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -334,6 +334,15 @@ void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned 
nr)
 }
 EXPORT_SYMBOL_GPL(kvm_requeue_exception);
 
+void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err)
+{
+   if (err)
+   kvm_inject_gp(vcpu, 0);
+   else
+   kvm_x86_ops-skip_emulated_instruction(vcpu);
+}
+EXPORT_SYMBOL_GPL(kvm_complete_insn_gp);
+
 void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
 {
++vcpu-stat.pf_guest;
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/8] kvm: cleanup emulate_instruction

2010-12-21 Thread Andre Przywara
emulate_instruction had many callers, but only one used all
parameters. One parameter was unused, another one is now
hidden by a wrapper function (required for a future addition
anyway), so most callers use now a shorter parameter list.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/include/asm/kvm_host.h |   11 +--
 arch/x86/kvm/mmu.c  |2 +-
 arch/x86/kvm/svm.c  |   14 +++---
 arch/x86/kvm/vmx.c  |   12 ++--
 arch/x86/kvm/x86.c  |   11 +--
 5 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index cd4a990..de00b60 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -634,8 +634,15 @@ enum emulation_result {
 #define EMULTYPE_NO_DECODE (1  0)
 #define EMULTYPE_TRAP_UD   (1  1)
 #define EMULTYPE_SKIP  (1  2)
-int emulate_instruction(struct kvm_vcpu *vcpu,
-   unsigned long cr2, u16 error_code, int emulation_type);
+int x86_emulate_instruction(struct kvm_vcpu *vcpu,
+   unsigned long cr2, int emulation_type);
+
+static inline int emulate_instruction(struct kvm_vcpu *vcpu,
+   int emulation_type)
+{
+   return x86_emulate_instruction(vcpu, 0, emulation_type);
+}
+
 void realmode_lgdt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
 void realmode_lidt(struct kvm_vcpu *vcpu, u16 size, unsigned long address);
 
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c3853d5..75334de 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3347,7 +3347,7 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, 
u32 error_code)
if (r)
goto out;
 
-   er = emulate_instruction(vcpu, cr2, error_code, 0);
+   er = x86_emulate_instruction(vcpu, cr2, 0);
 
switch (er) {
case EMULATE_DONE:
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 06a0892..d49d73c 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -475,7 +475,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
svm-next_rip = svm-vmcb-control.next_rip;
 
if (!svm-next_rip) {
-   if (emulate_instruction(vcpu, 0, 0, EMULTYPE_SKIP) !=
+   if (emulate_instruction(vcpu, EMULTYPE_SKIP) !=
EMULATE_DONE)
printk(KERN_DEBUG %s: NOP\n, __func__);
return;
@@ -1586,7 +1586,7 @@ static int ud_interception(struct vcpu_svm *svm)
 {
int er;
 
-   er = emulate_instruction(svm-vcpu, 0, 0, EMULTYPE_TRAP_UD);
+   er = emulate_instruction(svm-vcpu, EMULTYPE_TRAP_UD);
if (er != EMULATE_DONE)
kvm_queue_exception(svm-vcpu, UD_VECTOR);
return 1;
@@ -1703,7 +1703,7 @@ static int io_interception(struct vcpu_svm *svm)
string = (io_info  SVM_IOIO_STR_MASK) != 0;
in = (io_info  SVM_IOIO_TYPE_MASK) != 0;
if (string || in)
-   return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE;
+   return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 
port = io_info  16;
size = (io_info  SVM_IOIO_SIZE_MASK)  SVM_IOIO_SIZE_SHIFT;
@@ -2648,12 +2648,12 @@ static int iret_interception(struct vcpu_svm *svm)
 
 static int invlpg_interception(struct vcpu_svm *svm)
 {
-   return emulate_instruction(svm-vcpu, 0, 0, 0) == EMULATE_DONE;
+   return emulate_instruction(svm-vcpu, 0) == EMULATE_DONE;
 }
 
 static int emulate_on_interception(struct vcpu_svm *svm)
 {
-   return emulate_instruction(svm-vcpu, 0, 0, 0) == EMULATE_DONE;
+   return emulate_instruction(svm-vcpu, 0) == EMULATE_DONE;
 }
 
 static int cr0_write_interception(struct vcpu_svm *svm)
@@ -2661,7 +2661,7 @@ static int cr0_write_interception(struct vcpu_svm *svm)
struct kvm_vcpu *vcpu = svm-vcpu;
int r;
 
-   r = emulate_instruction(svm-vcpu, 0, 0, 0);
+   r = emulate_instruction(svm-vcpu, 0);
 
if (svm-nested.vmexit_rip) {
kvm_register_write(vcpu, VCPU_REGS_RIP, svm-nested.vmexit_rip);
@@ -2680,7 +2680,7 @@ static int cr8_write_interception(struct vcpu_svm *svm)
 
u8 cr8_prev = kvm_get_cr8(svm-vcpu);
/* instruction emulation calls kvm_set_cr8() */
-   r = emulate_instruction(svm-vcpu, 0, 0, 0);
+   r = emulate_instruction(svm-vcpu, 0);
if (irqchip_in_kernel(svm-vcpu.kvm)) {
clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
return r == EMULATE_DONE;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index fd8ffde..f3c60fb 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2939,7 +2939,7 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
 * Cause the #SS fault with 0 error code in VM86 mode.
 */
if (((vec == GP_VECTOR) || (vec == SS_VECTOR))  err_code == 0

[PATCH 1/8] kvm: fix CR8 handling

2010-12-21 Thread Andre Przywara
The handling of CR8 writes in KVM is currently somewhat cumbersome.
This patch makes it look like the other CR register handlers
and fixes a possible issue in VMX, where the RIP would be incremented
despite an injected #GP.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/include/asm/kvm_host.h |2 +-
 arch/x86/kvm/svm.c  |7 ---
 arch/x86/kvm/vmx.c  |4 ++--
 arch/x86/kvm/x86.c  |   18 --
 4 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4461429..cb5cad2 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -661,7 +661,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 
tss_selector, int reason,
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
+int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8);
 int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val);
 int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val);
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 24b4373..06a0892 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2676,16 +2676,17 @@ static int cr0_write_interception(struct vcpu_svm *svm)
 static int cr8_write_interception(struct vcpu_svm *svm)
 {
struct kvm_run *kvm_run = svm-vcpu.run;
+   int r;
 
u8 cr8_prev = kvm_get_cr8(svm-vcpu);
/* instruction emulation calls kvm_set_cr8() */
-   emulate_instruction(svm-vcpu, 0, 0, 0);
+   r = emulate_instruction(svm-vcpu, 0, 0, 0);
if (irqchip_in_kernel(svm-vcpu.kvm)) {
clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
-   return 1;
+   return r == EMULATE_DONE;
}
if (cr8_prev = kvm_get_cr8(svm-vcpu))
-   return 1;
+   return r == EMULATE_DONE;
kvm_run-exit_reason = KVM_EXIT_SET_TPR;
return 0;
 }
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c195260..8e87bae 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3185,8 +3185,8 @@ static int handle_cr(struct kvm_vcpu *vcpu)
case 8: {
u8 cr8_prev = kvm_get_cr8(vcpu);
u8 cr8 = kvm_register_read(vcpu, reg);
-   kvm_set_cr8(vcpu, cr8);
-   skip_emulated_instruction(vcpu);
+   err = kvm_set_cr8(vcpu, cr8);
+   complete_insn_gp(vcpu, err);
if (irqchip_in_kernel(vcpu-kvm))
return 1;
if (cr8_prev = cr8)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f569da8..2dbf68c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -662,7 +662,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr3);
 
-int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
+int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
if (cr8  CR8_RESERVED_BITS)
return 1;
@@ -672,12 +672,6 @@ int __kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
vcpu-arch.cr8 = cr8;
return 0;
 }
-
-void kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
-{
-   if (__kvm_set_cr8(vcpu, cr8))
-   kvm_inject_gp(vcpu, 0);
-}
 EXPORT_SYMBOL_GPL(kvm_set_cr8);
 
 unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu)
@@ -4104,7 +4098,7 @@ static int emulator_set_cr(int cr, unsigned long val, 
struct kvm_vcpu *vcpu)
res = kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
break;
case 8:
-   res = __kvm_set_cr8(vcpu, val  0xfUL);
+   res = kvm_set_cr8(vcpu, val);
break;
default:
vcpu_printf(vcpu, %s: unexpected cr %u\n, __func__, cr);
@@ -5381,8 +5375,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, 
struct kvm_run *kvm_run)
}
 
/* re-sync apic's tpr */
-   if (!irqchip_in_kernel(vcpu-kvm))
-   kvm_set_cr8(vcpu, kvm_run-cr8);
+   if (!irqchip_in_kernel(vcpu-kvm)) {
+   if (kvm_set_cr8(vcpu, kvm_run-cr8) != 0) {
+   r = -EINVAL;
+   goto out;
+   }
+   }
 
if (vcpu-arch.pio.count || vcpu-mmio_needed) {
if (vcpu-mmio_needed) {
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/8] kvm/svm: implement enhanced INVLPG intercept

2010-12-21 Thread Andre Przywara
When the DecodeAssist feature is available, the linear address
is provided in the VMCB on INVLPG intercepts. Use it directly to
avoid any decoding and emulation.
This is only useful for shadow paging, though.

Signed-off-by: Andre Przywara andre.przyw...@amd.com
---
 arch/x86/kvm/svm.c |7 ++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index eb662da..7871702 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2652,7 +2652,12 @@ static int iret_interception(struct vcpu_svm *svm)
 
 static int invlpg_interception(struct vcpu_svm *svm)
 {
-   return emulate_instruction(svm-vcpu, 0) == EMULATE_DONE;
+   if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
+   return emulate_instruction(svm-vcpu, 0) == EMULATE_DONE;
+
+   kvm_mmu_invlpg(svm-vcpu, svm-vmcb-control.exit_info_1);
+   skip_emulated_instruction(svm-vcpu);
+   return 1;
 }
 
 static int emulate_on_interception(struct vcpu_svm *svm)
-- 
1.6.4


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


<    1   2   3   4   5   6   7   >