* [PULL 0/6] ppc patch queue 2013-05-02 for 3.10
@ 2013-05-02 13:32 Alexander Graf
2013-05-02 13:32 ` [PATCH 1/6] kvm/ppc/mpic: remove default routes from documentation Alexander Graf
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc; +Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti
Hi Marcelo / Gleb,
This is my current patch queue for ppc. Please pull and apply to next, so it
makes its way into 3.10. Sorry for the late request.
There is still one RCU patch outstanding that needs a respin, so expect another
request to come in later in the 3.10 cycle.
Changes include:
- Book3S HV: Expose in-kernel XICS device creation, enabling in-kernel irqchip
on POWER systems.
- Various MPIC and RCU bug fixes
Alex
The following changes since commit 4cee4b72f1e2600e19779a14d4d9a4f4016ce49f:
kvm: KVM_CAP_IOMMU only available with device assignment (2013-04-29 23:08:50 -0300)
are available in the git repository at:
git://github.com/agraf/linux-2.6.git kvm-ppc-next
for you to fetch changes up to 5975a2e0950291a6bfe9fd5880e7952ff87764be:
KVM: PPC: Book3S: Add API for in-kernel XICS emulation (2013-05-02 15:28:36 +0200)
----------------------------------------------------------------
Paul Mackerras (1):
KVM: PPC: Book3S: Add API for in-kernel XICS emulation
Scott Wood (4):
kvm/ppc/mpic: remove default routes from documentation
kvm/ppc/mpic: fix mmio region lists when multiple guests used
kvm/ppc/mpic: remove users
kvm/ppc: Hold srcu lock when calling kvm_io_bus_read/write
Wei Yongjun (1):
kvm/ppc/mpic: fix missing unlock in set_base_addr()
Documentation/virtual/kvm/api.txt | 8 ++
Documentation/virtual/kvm/devices/mpic.txt | 3 -
Documentation/virtual/kvm/devices/xics.txt | 66 ++++++++++
arch/powerpc/include/asm/kvm_ppc.h | 2 +
arch/powerpc/include/uapi/asm/kvm.h | 12 ++
arch/powerpc/kvm/book3s_xics.c | 190 +++++++++++++++++++++++++----
arch/powerpc/kvm/book3s_xics.h | 1 +
arch/powerpc/kvm/irq.h | 3 +
arch/powerpc/kvm/mpic.c | 56 +++++----
arch/powerpc/kvm/powerpc.c | 45 ++++++-
include/linux/kvm_host.h | 1 +
include/uapi/linux/kvm.h | 2 +
virt/kvm/kvm_main.c | 5 +
13 files changed, 339 insertions(+), 55 deletions(-)
create mode 100644 Documentation/virtual/kvm/devices/xics.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/6] kvm/ppc/mpic: remove default routes from documentation
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
@ 2013-05-02 13:32 ` Alexander Graf
2013-05-02 13:32 ` [PATCH 2/6] kvm/ppc/mpic: fix mmio region lists when multiple guests used Alexander Graf
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc
Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti,
Scott Wood
From: Scott Wood <scottwood@freescale.com>
The default routes were removed from the code during patchset
respinning, but were not removed from the documentation.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Documentation/virtual/kvm/devices/mpic.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Documentation/virtual/kvm/devices/mpic.txt b/Documentation/virtual/kvm/devices/mpic.txt
index ad0ac77..8257397 100644
--- a/Documentation/virtual/kvm/devices/mpic.txt
+++ b/Documentation/virtual/kvm/devices/mpic.txt
@@ -50,7 +50,4 @@ IRQ Routing:
regard to any subdivisions in chip documentation such as "internal"
or "external" interrupts.
- Default routes are established for these pins, with the GSI being equal
- to the pin number.
-
Access to non-SRC interrupts is not implemented through IRQ routing mechanisms.
--
1.8.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/6] kvm/ppc/mpic: fix mmio region lists when multiple guests used
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
2013-05-02 13:32 ` [PATCH 1/6] kvm/ppc/mpic: remove default routes from documentation Alexander Graf
@ 2013-05-02 13:32 ` Alexander Graf
2013-05-02 13:32 ` [PATCH 3/6] kvm/ppc/mpic: remove users Alexander Graf
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc
Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti,
Scott Wood
From: Scott Wood <scottwood@freescale.com>
Keeping a linked list of statically defined objects doesn't work
very well when we have multiple guests. :-P
Switch to an array of constant objects. This fixes a hang when
multiple guests are used.
Signed-off-by: Scott Wood <scottwood@freescale.com>
[agraf: remove struct list_head from mem_reg]
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/mpic.c | 53 +++++++++++++++++++++++++++++--------------------
1 file changed, 32 insertions(+), 21 deletions(-)
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c
index f3148f8..886ebf6 100644
--- a/arch/powerpc/kvm/mpic.c
+++ b/arch/powerpc/kvm/mpic.c
@@ -184,11 +184,14 @@ struct irq_dest {
uint32_t outputs_active[NUM_OUTPUTS];
};
+#define MAX_MMIO_REGIONS 10
+
struct openpic {
struct kvm *kvm;
struct kvm_device *dev;
struct kvm_io_device mmio;
- struct list_head mmio_regions;
+ const struct mem_reg *mmio_regions[MAX_MMIO_REGIONS];
+ int num_mmio_regions;
atomic_t users;
gpa_t reg_base;
@@ -1238,62 +1241,71 @@ static int openpic_cpu_read(void *opaque, gpa_t addr, u32 *ptr)
}
struct mem_reg {
- struct list_head list;
int (*read)(void *opaque, gpa_t addr, u32 *ptr);
int (*write)(void *opaque, gpa_t addr, u32 val);
gpa_t start_addr;
int size;
};
-static struct mem_reg openpic_gbl_mmio = {
+static const struct mem_reg openpic_gbl_mmio = {
.write = openpic_gbl_write,
.read = openpic_gbl_read,
.start_addr = OPENPIC_GLB_REG_START,
.size = OPENPIC_GLB_REG_SIZE,
};
-static struct mem_reg openpic_tmr_mmio = {
+static const struct mem_reg openpic_tmr_mmio = {
.write = openpic_tmr_write,
.read = openpic_tmr_read,
.start_addr = OPENPIC_TMR_REG_START,
.size = OPENPIC_TMR_REG_SIZE,
};
-static struct mem_reg openpic_cpu_mmio = {
+static const struct mem_reg openpic_cpu_mmio = {
.write = openpic_cpu_write,
.read = openpic_cpu_read,
.start_addr = OPENPIC_CPU_REG_START,
.size = OPENPIC_CPU_REG_SIZE,
};
-static struct mem_reg openpic_src_mmio = {
+static const struct mem_reg openpic_src_mmio = {
.write = openpic_src_write,
.read = openpic_src_read,
.start_addr = OPENPIC_SRC_REG_START,
.size = OPENPIC_SRC_REG_SIZE,
};
-static struct mem_reg openpic_msi_mmio = {
+static const struct mem_reg openpic_msi_mmio = {
.read = openpic_msi_read,
.write = openpic_msi_write,
.start_addr = OPENPIC_MSI_REG_START,
.size = OPENPIC_MSI_REG_SIZE,
};
-static struct mem_reg openpic_summary_mmio = {
+static const struct mem_reg openpic_summary_mmio = {
.read = openpic_summary_read,
.write = openpic_summary_write,
.start_addr = OPENPIC_SUMMARY_REG_START,
.size = OPENPIC_SUMMARY_REG_SIZE,
};
+static void add_mmio_region(struct openpic *opp, const struct mem_reg *mr)
+{
+ if (opp->num_mmio_regions >= MAX_MMIO_REGIONS) {
+ WARN(1, "kvm mpic: too many mmio regions\n");
+ return;
+ }
+
+ opp->mmio_regions[opp->num_mmio_regions++] = mr;
+}
+
static void fsl_common_init(struct openpic *opp)
{
int i;
int virq = MAX_SRC;
- list_add(&openpic_msi_mmio.list, &opp->mmio_regions);
- list_add(&openpic_summary_mmio.list, &opp->mmio_regions);
+ add_mmio_region(opp, &openpic_msi_mmio);
+ add_mmio_region(opp, &openpic_summary_mmio);
opp->vid = VID_REVISION_1_2;
opp->vir = VIR_GENERIC;
@@ -1330,10 +1342,10 @@ static void fsl_common_init(struct openpic *opp)
static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr)
{
- struct list_head *node;
+ int i;
- list_for_each(node, &opp->mmio_regions) {
- struct mem_reg *mr = list_entry(node, struct mem_reg, list);
+ for (i = 0; i < opp->num_mmio_regions; i++) {
+ const struct mem_reg *mr = opp->mmio_regions[i];
if (mr->start_addr > addr || addr >= mr->start_addr + mr->size)
continue;
@@ -1346,10 +1358,10 @@ static int kvm_mpic_read_internal(struct openpic *opp, gpa_t addr, u32 *ptr)
static int kvm_mpic_write_internal(struct openpic *opp, gpa_t addr, u32 val)
{
- struct list_head *node;
+ int i;
- list_for_each(node, &opp->mmio_regions) {
- struct mem_reg *mr = list_entry(node, struct mem_reg, list);
+ for (i = 0; i < opp->num_mmio_regions; i++) {
+ const struct mem_reg *mr = opp->mmio_regions[i];
if (mr->start_addr > addr || addr >= mr->start_addr + mr->size)
continue;
@@ -1660,11 +1672,10 @@ static int mpic_create(struct kvm_device *dev, u32 type)
opp->model = type;
spin_lock_init(&opp->lock);
- INIT_LIST_HEAD(&opp->mmio_regions);
- list_add(&openpic_gbl_mmio.list, &opp->mmio_regions);
- list_add(&openpic_tmr_mmio.list, &opp->mmio_regions);
- list_add(&openpic_src_mmio.list, &opp->mmio_regions);
- list_add(&openpic_cpu_mmio.list, &opp->mmio_regions);
+ add_mmio_region(opp, &openpic_gbl_mmio);
+ add_mmio_region(opp, &openpic_tmr_mmio);
+ add_mmio_region(opp, &openpic_src_mmio);
+ add_mmio_region(opp, &openpic_cpu_mmio);
switch (opp->model) {
case KVM_DEV_TYPE_FSL_MPIC_20:
--
1.8.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] kvm/ppc/mpic: remove users
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
2013-05-02 13:32 ` [PATCH 1/6] kvm/ppc/mpic: remove default routes from documentation Alexander Graf
2013-05-02 13:32 ` [PATCH 2/6] kvm/ppc/mpic: fix mmio region lists when multiple guests used Alexander Graf
@ 2013-05-02 13:32 ` Alexander Graf
2013-05-02 13:32 ` [PATCH 4/6] kvm/ppc: Hold srcu lock when calling kvm_io_bus_read/write Alexander Graf
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc
Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti,
Scott Wood
From: Scott Wood <scottwood@freescale.com>
This is an unused (no pun intended) leftover from when this code did
reference counting.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/mpic.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c
index 886ebf6..eaac187 100644
--- a/arch/powerpc/kvm/mpic.c
+++ b/arch/powerpc/kvm/mpic.c
@@ -192,7 +192,6 @@ struct openpic {
struct kvm_io_device mmio;
const struct mem_reg *mmio_regions[MAX_MMIO_REGIONS];
int num_mmio_regions;
- atomic_t users;
gpa_t reg_base;
spinlock_t lock;
--
1.8.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/6] kvm/ppc: Hold srcu lock when calling kvm_io_bus_read/write
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
` (2 preceding siblings ...)
2013-05-02 13:32 ` [PATCH 3/6] kvm/ppc/mpic: remove users Alexander Graf
@ 2013-05-02 13:32 ` Alexander Graf
2013-05-02 13:32 ` [PATCH 5/6] kvm/ppc/mpic: fix missing unlock in set_base_addr() Alexander Graf
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc
Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti,
Scott Wood
From: Scott Wood <scottwood@freescale.com>
These functions do an srcu_dereference without acquiring the srcu lock
themselves.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/powerpc.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 31084c6..270773f 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -622,6 +622,8 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int rt, unsigned int bytes, int is_bigendian)
{
+ int idx, ret;
+
if (bytes > sizeof(run->mmio.data)) {
printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
run->mmio.len);
@@ -637,8 +639,14 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
vcpu->mmio_is_write = 0;
vcpu->arch.mmio_sign_extend = 0;
- if (!kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
- bytes, &run->mmio.data)) {
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ ret = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+ bytes, &run->mmio.data);
+
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+ if (!ret) {
kvmppc_complete_mmio_load(vcpu, run);
vcpu->mmio_needed = 0;
return EMULATE_DONE;
@@ -663,6 +671,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
u64 val, unsigned int bytes, int is_bigendian)
{
void *data = run->mmio.data;
+ int idx, ret;
if (bytes > sizeof(run->mmio.data)) {
printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__,
@@ -692,8 +701,14 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
}
}
- if (!kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
- bytes, &run->mmio.data)) {
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ ret = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, run->mmio.phys_addr,
+ bytes, &run->mmio.data);
+
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+ if (!ret) {
vcpu->mmio_needed = 0;
return EMULATE_DONE;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/6] kvm/ppc/mpic: fix missing unlock in set_base_addr()
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
` (3 preceding siblings ...)
2013-05-02 13:32 ` [PATCH 4/6] kvm/ppc: Hold srcu lock when calling kvm_io_bus_read/write Alexander Graf
@ 2013-05-02 13:32 ` Alexander Graf
2013-05-02 13:32 ` [PATCH 6/6] KVM: PPC: Book3S: Add API for in-kernel XICS emulation Alexander Graf
2013-05-03 0:09 ` [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Marcelo Tosatti
6 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc
Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti,
Wei Yongjun
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Add the missing unlock before return from function set_base_addr()
when disables the mapping.
Introduced by commit 5df554ad5b7522ea62b0ff9d5be35183494efc21
(kvm/ppc/mpic: in-kernel MPIC emulation)
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/mpic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c
index eaac187..2861ae9 100644
--- a/arch/powerpc/kvm/mpic.c
+++ b/arch/powerpc/kvm/mpic.c
@@ -1486,8 +1486,8 @@ static int set_base_addr(struct openpic *opp, struct kvm_device_attr *attr)
map_mmio(opp);
- mutex_unlock(&opp->kvm->slots_lock);
out:
+ mutex_unlock(&opp->kvm->slots_lock);
return 0;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/6] KVM: PPC: Book3S: Add API for in-kernel XICS emulation
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
` (4 preceding siblings ...)
2013-05-02 13:32 ` [PATCH 5/6] kvm/ppc/mpic: fix missing unlock in set_base_addr() Alexander Graf
@ 2013-05-02 13:32 ` Alexander Graf
2013-05-03 0:09 ` [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Marcelo Tosatti
6 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2013-05-02 13:32 UTC (permalink / raw)
To: kvm-ppc
Cc: kvm@vger.kernel.org mailing list, Gleb Natapov, Marcelo Tosatti,
Paul Mackerras
From: Paul Mackerras <paulus@samba.org>
This adds the API for userspace to instantiate an XICS device in a VM
and connect VCPUs to it. The API consists of a new device type for
the KVM_CREATE_DEVICE ioctl, a new capability KVM_CAP_IRQ_XICS, which
functions similarly to KVM_CAP_IRQ_MPIC, and the KVM_IRQ_LINE ioctl,
which is used to assert and deassert interrupt inputs of the XICS.
The XICS device has one attribute group, KVM_DEV_XICS_GRP_SOURCES.
Each attribute within this group corresponds to the state of one
interrupt source. The attribute number is the same as the interrupt
source number.
This does not support irq routing or irqfd yet.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Documentation/virtual/kvm/api.txt | 8 ++
Documentation/virtual/kvm/devices/xics.txt | 66 ++++++++++
arch/powerpc/include/asm/kvm_ppc.h | 2 +
arch/powerpc/include/uapi/asm/kvm.h | 12 ++
arch/powerpc/kvm/book3s_xics.c | 190 +++++++++++++++++++++++++----
arch/powerpc/kvm/book3s_xics.h | 1 +
arch/powerpc/kvm/irq.h | 3 +
arch/powerpc/kvm/powerpc.c | 22 ++++
include/linux/kvm_host.h | 1 +
include/uapi/linux/kvm.h | 2 +
virt/kvm/kvm_main.c | 5 +
11 files changed, 287 insertions(+), 25 deletions(-)
create mode 100644 Documentation/virtual/kvm/devices/xics.txt
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index c09d183..03492f9 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2772,3 +2772,11 @@ Parameters: args[0] is the MPIC device fd
args[1] is the MPIC CPU number for this vcpu
This capability connects the vcpu to an in-kernel MPIC device.
+
+6.7 KVM_CAP_IRQ_XICS
+
+Architectures: ppc
+Parameters: args[0] is the XICS device fd
+ args[1] is the XICS CPU number (server ID) for this vcpu
+
+This capability connects the vcpu to an in-kernel XICS device.
diff --git a/Documentation/virtual/kvm/devices/xics.txt b/Documentation/virtual/kvm/devices/xics.txt
new file mode 100644
index 0000000..4286493
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/xics.txt
@@ -0,0 +1,66 @@
+XICS interrupt controller
+
+Device type supported: KVM_DEV_TYPE_XICS
+
+Groups:
+ KVM_DEV_XICS_SOURCES
+ Attributes: One per interrupt source, indexed by the source number.
+
+This device emulates the XICS (eXternal Interrupt Controller
+Specification) defined in PAPR. The XICS has a set of interrupt
+sources, each identified by a 20-bit source number, and a set of
+Interrupt Control Presentation (ICP) entities, also called "servers",
+each associated with a virtual CPU.
+
+The ICP entities are created by enabling the KVM_CAP_IRQ_ARCH
+capability for each vcpu, specifying KVM_CAP_IRQ_XICS in args[0] and
+the interrupt server number (i.e. the vcpu number from the XICS's
+point of view) in args[1] of the kvm_enable_cap struct. Each ICP has
+64 bits of state which can be read and written using the
+KVM_GET_ONE_REG and KVM_SET_ONE_REG ioctls on the vcpu. The 64 bit
+state word has the following bitfields, starting at the
+least-significant end of the word:
+
+* Unused, 16 bits
+
+* Pending interrupt priority, 8 bits
+ Zero is the highest priority, 255 means no interrupt is pending.
+
+* Pending IPI (inter-processor interrupt) priority, 8 bits
+ Zero is the highest priority, 255 means no IPI is pending.
+
+* Pending interrupt source number, 24 bits
+ Zero means no interrupt pending, 2 means an IPI is pending
+
+* Current processor priority, 8 bits
+ Zero is the highest priority, meaning no interrupts can be
+ delivered, and 255 is the lowest priority.
+
+Each source has 64 bits of state that can be read and written using
+the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the
+KVM_DEV_XICS_SOURCES attribute group, with the attribute number being
+the interrupt source number. The 64 bit state word has the following
+bitfields, starting from the least-significant end of the word:
+
+* Destination (server number), 32 bits
+ This specifies where the interrupt should be sent, and is the
+ interrupt server number specified for the destination vcpu.
+
+* Priority, 8 bits
+ This is the priority specified for this interrupt source, where 0 is
+ the highest priority and 255 is the lowest. An interrupt with a
+ priority of 255 will never be delivered.
+
+* Level sensitive flag, 1 bit
+ This bit is 1 for a level-sensitive interrupt source, or 0 for
+ edge-sensitive (or MSI).
+
+* Masked flag, 1 bit
+ This bit is set to 1 if the interrupt is masked (cannot be delivered
+ regardless of its priority), for example by the ibm,int-off RTAS
+ call, or 0 if it is not masked.
+
+* Pending flag, 1 bit
+ This bit is 1 if the source has a pending interrupt, otherwise 0.
+
+Only one XICS instance may be created per VM.
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index d7339df..a5287fe 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -315,6 +315,8 @@ extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu);
extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
+extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev,
+ struct kvm_vcpu *vcpu, u32 cpu);
#else
static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
{ return 0; }
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 427b9ac..0fb1a6e 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -499,4 +499,16 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
#define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
+/* PPC64 eXternal Interrupt Controller Specification */
+#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
+
+/* Layout of 64-bit source attribute values */
+#define KVM_XICS_DESTINATION_SHIFT 0
+#define KVM_XICS_DESTINATION_MASK 0xffffffffULL
+#define KVM_XICS_PRIORITY_SHIFT 32
+#define KVM_XICS_PRIORITY_MASK 0xff
+#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40)
+#define KVM_XICS_MASKED (1ULL << 41)
+#define KVM_XICS_PENDING (1ULL << 42)
+
#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index ee841ed..f7a1037 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -11,6 +11,7 @@
#include <linux/kvm_host.h>
#include <linux/err.h>
#include <linux/gfp.h>
+#include <linux/anon_inodes.h>
#include <asm/uaccess.h>
#include <asm/kvm_book3s.h>
@@ -55,8 +56,6 @@
*
* - Make ICS lockless as well, or at least a per-interrupt lock or hashed
* locks array to improve scalability
- *
- * - ioctl's to save/restore the entire state for snapshot & migration
*/
/* -- ICS routines -- */
@@ -64,7 +63,8 @@
static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
u32 new_irq);
-static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
+static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level,
+ bool report_status)
{
struct ics_irq_state *state;
struct kvmppc_ics *ics;
@@ -81,6 +81,9 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
if (!state->exists)
return -EINVAL;
+ if (report_status)
+ return state->asserted;
+
/*
* We set state->asserted locklessly. This should be fine as
* we are the only setter, thus concurrent access is undefined
@@ -96,7 +99,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level)
/* Attempt delivery */
icp_deliver_irq(xics, NULL, irq);
- return 0;
+ return state->asserted;
}
static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
@@ -891,8 +894,8 @@ static void xics_debugfs_init(struct kvmppc_xics *xics)
kfree(name);
}
-struct kvmppc_ics *kvmppc_xics_create_ics(struct kvm *kvm,
- struct kvmppc_xics *xics, int irq)
+static struct kvmppc_ics *kvmppc_xics_create_ics(struct kvm *kvm,
+ struct kvmppc_xics *xics, int irq)
{
struct kvmppc_ics *ics;
int i, icsid;
@@ -1044,34 +1047,138 @@ int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval)
return 0;
}
-/* -- ioctls -- */
+static int xics_get_source(struct kvmppc_xics *xics, long irq, u64 addr)
+{
+ int ret;
+ struct kvmppc_ics *ics;
+ struct ics_irq_state *irqp;
+ u64 __user *ubufp = (u64 __user *) addr;
+ u16 idx;
+ u64 val, prio;
+
+ ics = kvmppc_xics_find_ics(xics, irq, &idx);
+ if (!ics)
+ return -ENOENT;
-int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args)
+ irqp = &ics->irq_state[idx];
+ mutex_lock(&ics->lock);
+ ret = -ENOENT;
+ if (irqp->exists) {
+ val = irqp->server;
+ prio = irqp->priority;
+ if (prio = MASKED) {
+ val |= KVM_XICS_MASKED;
+ prio = irqp->saved_priority;
+ }
+ val |= prio << KVM_XICS_PRIORITY_SHIFT;
+ if (irqp->asserted)
+ val |= KVM_XICS_LEVEL_SENSITIVE | KVM_XICS_PENDING;
+ else if (irqp->masked_pending || irqp->resend)
+ val |= KVM_XICS_PENDING;
+ ret = 0;
+ }
+ mutex_unlock(&ics->lock);
+
+ if (!ret && put_user(val, ubufp))
+ ret = -EFAULT;
+
+ return ret;
+}
+
+static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr)
{
- struct kvmppc_xics *xics;
- int r;
+ struct kvmppc_ics *ics;
+ struct ics_irq_state *irqp;
+ u64 __user *ubufp = (u64 __user *) addr;
+ u16 idx;
+ u64 val;
+ u8 prio;
+ u32 server;
+
+ if (irq < KVMPPC_XICS_FIRST_IRQ || irq >= KVMPPC_XICS_NR_IRQS)
+ return -ENOENT;
+
+ ics = kvmppc_xics_find_ics(xics, irq, &idx);
+ if (!ics) {
+ ics = kvmppc_xics_create_ics(xics->kvm, xics, irq);
+ if (!ics)
+ return -ENOMEM;
+ }
+ irqp = &ics->irq_state[idx];
+ if (get_user(val, ubufp))
+ return -EFAULT;
+
+ server = val & KVM_XICS_DESTINATION_MASK;
+ prio = val >> KVM_XICS_PRIORITY_SHIFT;
+ if (prio != MASKED &&
+ kvmppc_xics_find_server(xics->kvm, server) = NULL)
+ return -EINVAL;
- /* locking against multiple callers? */
+ mutex_lock(&ics->lock);
+ irqp->server = server;
+ irqp->saved_priority = prio;
+ if (val & KVM_XICS_MASKED)
+ prio = MASKED;
+ irqp->priority = prio;
+ irqp->resend = 0;
+ irqp->masked_pending = 0;
+ irqp->asserted = 0;
+ if ((val & KVM_XICS_PENDING) && (val & KVM_XICS_LEVEL_SENSITIVE))
+ irqp->asserted = 1;
+ irqp->exists = 1;
+ mutex_unlock(&ics->lock);
- xics = kvm->arch.xics;
- if (!xics)
- return -ENODEV;
+ if (val & KVM_XICS_PENDING)
+ icp_deliver_irq(xics, NULL, irqp->number);
- switch (args->level) {
- case KVM_INTERRUPT_SET:
- case KVM_INTERRUPT_SET_LEVEL:
- case KVM_INTERRUPT_UNSET:
- r = ics_deliver_irq(xics, args->irq, args->level);
- break;
- default:
- r = -EINVAL;
+ return 0;
+}
+
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
+ bool line_status)
+{
+ struct kvmppc_xics *xics = kvm->arch.xics;
+
+ return ics_deliver_irq(xics, irq, level, line_status);
+}
+
+static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+ struct kvmppc_xics *xics = dev->private;
+
+ switch (attr->group) {
+ case KVM_DEV_XICS_GRP_SOURCES:
+ return xics_set_source(xics, attr->attr, attr->addr);
}
+ return -ENXIO;
+}
- return r;
+static int xics_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+ struct kvmppc_xics *xics = dev->private;
+
+ switch (attr->group) {
+ case KVM_DEV_XICS_GRP_SOURCES:
+ return xics_get_source(xics, attr->attr, attr->addr);
+ }
+ return -ENXIO;
}
-void kvmppc_xics_free(struct kvmppc_xics *xics)
+static int xics_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
{
+ switch (attr->group) {
+ case KVM_DEV_XICS_GRP_SOURCES:
+ if (attr->attr >= KVMPPC_XICS_FIRST_IRQ &&
+ attr->attr < KVMPPC_XICS_NR_IRQS)
+ return 0;
+ break;
+ }
+ return -ENXIO;
+}
+
+static void kvmppc_xics_free(struct kvm_device *dev)
+{
+ struct kvmppc_xics *xics = dev->private;
int i;
struct kvm *kvm = xics->kvm;
@@ -1083,17 +1190,21 @@ void kvmppc_xics_free(struct kvmppc_xics *xics)
for (i = 0; i <= xics->max_icsid; i++)
kfree(xics->ics[i]);
kfree(xics);
+ kfree(dev);
}
-int kvm_xics_create(struct kvm *kvm, u32 type)
+static int kvmppc_xics_create(struct kvm_device *dev, u32 type)
{
struct kvmppc_xics *xics;
+ struct kvm *kvm = dev->kvm;
int ret = 0;
xics = kzalloc(sizeof(*xics), GFP_KERNEL);
if (!xics)
return -ENOMEM;
+ dev->private = xics;
+ xics->dev = dev;
xics->kvm = kvm;
/* Already there ? */
@@ -1120,6 +1231,35 @@ int kvm_xics_create(struct kvm *kvm, u32 type)
return 0;
}
+struct kvm_device_ops kvm_xics_ops = {
+ .name = "kvm-xics",
+ .create = kvmppc_xics_create,
+ .destroy = kvmppc_xics_free,
+ .set_attr = xics_set_attr,
+ .get_attr = xics_get_attr,
+ .has_attr = xics_has_attr,
+};
+
+int kvmppc_xics_connect_vcpu(struct kvm_device *dev, struct kvm_vcpu *vcpu,
+ u32 xcpu)
+{
+ struct kvmppc_xics *xics = dev->private;
+ int r = -EBUSY;
+
+ if (dev->ops != &kvm_xics_ops)
+ return -EPERM;
+ if (xics->kvm != vcpu->kvm)
+ return -EPERM;
+ if (vcpu->arch.irq_type)
+ return -EBUSY;
+
+ r = kvmppc_xics_create_icp(vcpu, xcpu);
+ if (!r)
+ vcpu->arch.irq_type = KVMPPC_IRQ_XICS;
+
+ return r;
+}
+
void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
{
if (!vcpu->arch.icp)
diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h
index e4fdec3..dd9326c 100644
--- a/arch/powerpc/kvm/book3s_xics.h
+++ b/arch/powerpc/kvm/book3s_xics.h
@@ -88,6 +88,7 @@ struct kvmppc_ics {
struct kvmppc_xics {
struct kvm *kvm;
+ struct kvm_device *dev;
struct dentry *dentry;
u32 max_icsid;
bool real_mode;
diff --git a/arch/powerpc/kvm/irq.h b/arch/powerpc/kvm/irq.h
index f1e27fd..5a9a10b 100644
--- a/arch/powerpc/kvm/irq.h
+++ b/arch/powerpc/kvm/irq.h
@@ -10,6 +10,9 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
#ifdef CONFIG_KVM_MPIC
ret = ret || (kvm->arch.mpic != NULL);
#endif
+#ifdef CONFIG_KVM_XICS
+ ret = ret || (kvm->arch.xics != NULL);
+#endif
smp_rmb();
return ret;
}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 270773f..6316ee3 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -342,6 +342,9 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_SPAPR_TCE:
case KVM_CAP_PPC_ALLOC_HTAB:
case KVM_CAP_PPC_RTAS:
+#ifdef CONFIG_KVM_XICS
+ case KVM_CAP_IRQ_XICS:
+#endif
r = 1;
break;
#endif /* CONFIG_PPC_BOOK3S_64 */
@@ -837,6 +840,25 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
break;
}
#endif
+#ifdef CONFIG_KVM_XICS
+ case KVM_CAP_IRQ_XICS: {
+ struct file *filp;
+ struct kvm_device *dev;
+
+ r = -EBADF;
+ filp = fget(cap->args[0]);
+ if (!filp)
+ break;
+
+ r = -EPERM;
+ dev = kvm_device_from_filp(filp);
+ if (dev)
+ r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
+
+ fput(filp);
+ break;
+ }
+#endif /* CONFIG_KVM_XICS */
default:
r = -EINVAL;
break;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 996661e..7823b63 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1086,6 +1086,7 @@ void kvm_device_put(struct kvm_device *dev);
struct kvm_device *kvm_device_from_filp(struct file *filp);
extern struct kvm_device_ops kvm_mpic_ops;
+extern struct kvm_device_ops kvm_xics_ops;
#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 965e5b5..a5c86fc 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -665,6 +665,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_DEVICE_CTRL 89
#define KVM_CAP_IRQ_MPIC 90
#define KVM_CAP_PPC_RTAS 91
+#define KVM_CAP_IRQ_XICS 92
#ifdef KVM_CAP_IRQ_ROUTING
@@ -837,6 +838,7 @@ struct kvm_device_attr {
#define KVM_DEV_TYPE_FSL_MPIC_20 1
#define KVM_DEV_TYPE_FSL_MPIC_42 2
+#define KVM_DEV_TYPE_XICS 3
/*
* ioctls for VM fds
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 5da9f02..e6e7abe 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2247,6 +2247,11 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
ops = &kvm_mpic_ops;
break;
#endif
+#ifdef CONFIG_KVM_XICS
+ case KVM_DEV_TYPE_XICS:
+ ops = &kvm_xics_ops;
+ break;
+#endif
default:
return -ENODEV;
}
--
1.8.1.4
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PULL 0/6] ppc patch queue 2013-05-02 for 3.10
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
` (5 preceding siblings ...)
2013-05-02 13:32 ` [PATCH 6/6] KVM: PPC: Book3S: Add API for in-kernel XICS emulation Alexander Graf
@ 2013-05-03 0:09 ` Marcelo Tosatti
6 siblings, 0 replies; 8+ messages in thread
From: Marcelo Tosatti @ 2013-05-03 0:09 UTC (permalink / raw)
To: Alexander Graf; +Cc: kvm-ppc, kvm@vger.kernel.org mailing list, Gleb Natapov
On Thu, May 02, 2013 at 03:32:45PM +0200, Alexander Graf wrote:
> Hi Marcelo / Gleb,
>
> This is my current patch queue for ppc. Please pull and apply to next, so it
> makes its way into 3.10. Sorry for the late request.
>
> There is still one RCU patch outstanding that needs a respin, so expect another
> request to come in later in the 3.10 cycle.
>
> Changes include:
>
> - Book3S HV: Expose in-kernel XICS device creation, enabling in-kernel irqchip
> on POWER systems.
> - Various MPIC and RCU bug fixes
>
> Alex
>
>
> The following changes since commit 4cee4b72f1e2600e19779a14d4d9a4f4016ce49f:
>
> kvm: KVM_CAP_IOMMU only available with device assignment (2013-04-29 23:08:50 -0300)
>
> are available in the git repository at:
>
> git://github.com/agraf/linux-2.6.git kvm-ppc-next
>
> for you to fetch changes up to 5975a2e0950291a6bfe9fd5880e7952ff87764be:
>
> KVM: PPC: Book3S: Add API for in-kernel XICS emulation (2013-05-02 15:28:36 +0200)
Pulled, thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-05-03 0:09 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-02 13:32 [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Alexander Graf
2013-05-02 13:32 ` [PATCH 1/6] kvm/ppc/mpic: remove default routes from documentation Alexander Graf
2013-05-02 13:32 ` [PATCH 2/6] kvm/ppc/mpic: fix mmio region lists when multiple guests used Alexander Graf
2013-05-02 13:32 ` [PATCH 3/6] kvm/ppc/mpic: remove users Alexander Graf
2013-05-02 13:32 ` [PATCH 4/6] kvm/ppc: Hold srcu lock when calling kvm_io_bus_read/write Alexander Graf
2013-05-02 13:32 ` [PATCH 5/6] kvm/ppc/mpic: fix missing unlock in set_base_addr() Alexander Graf
2013-05-02 13:32 ` [PATCH 6/6] KVM: PPC: Book3S: Add API for in-kernel XICS emulation Alexander Graf
2013-05-03 0:09 ` [PULL 0/6] ppc patch queue 2013-05-02 for 3.10 Marcelo Tosatti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox