* [Qemu-devel] [PATCH 0/3] sparc64 fixes
@ 2013-04-27 5:55 Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 1/3] sparc64: allow 64 IRQ lines Artyom Tarasenko
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Artyom Tarasenko @ 2013-04-27 5:55 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel, Artyom Tarasenko
Various fixes:
On the real hardware IRQ lines of the PCI bus are not shared.
In the previous QEMU implementation before this series, all PCI devices
used the IRQ line 0. Combined with auto-clearing interrupts this made
the guest OS extremely unstable. The test case is installing
Debian Wheezy / sparc64:
http://tyom.blogspot.de/2013/03/debiansparc64-wheezy-under-qemu-how-to.html
Without the patches the install process hangs at random places between 6% and 60%.
With this series the installation succeeds.
Please note that the patch 3/3 requires updating OpenBIOS.
Artyom Tarasenko (3):
sparc64: allow 64 IRQ lines
sparc64: fix loosing interrupts
sparc64: use direct interrupt mapping for PCI devices
hw/pci-host/apb.c | 118 +++++++++++++++++++++++++++++++++++++++++++---------
hw/sparc64/sun4u.c | 2 +-
2 files changed, 99 insertions(+), 21 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 1/3] sparc64: allow 64 IRQ lines
2013-04-27 5:55 [Qemu-devel] [PATCH 0/3] sparc64 fixes Artyom Tarasenko
@ 2013-04-27 5:55 ` Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 2/3] sparc64: fix loosing interrupts Artyom Tarasenko
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Artyom Tarasenko @ 2013-04-27 5:55 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel, Artyom Tarasenko
According to UltraSPARC™-IIi User’s Manual, PBM has 64 IRQ lines.
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
---
hw/pci-host/apb.c | 2 +-
hw/sparc64/sun4u.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index b4981d7..3bc0d10 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -66,7 +66,7 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
#define RESET_WCMASK 0x98000000
#define RESET_WMASK 0x60000000
-#define MAX_IVEC 0x30
+#define MAX_IVEC 0x40
typedef struct APBState {
SysBusDevice busdev;
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 0d29620..5c2bbd4 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -81,7 +81,7 @@
#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
-#define IVEC_MAX 0x30
+#define IVEC_MAX 0x40
#define TICK_MAX 0x7fffffffffffffffULL
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 2/3] sparc64: fix loosing interrupts
2013-04-27 5:55 [Qemu-devel] [PATCH 0/3] sparc64 fixes Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 1/3] sparc64: allow 64 IRQ lines Artyom Tarasenko
@ 2013-04-27 5:55 ` Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 3/3] sparc64: use direct interrupt mapping for PCI devices Artyom Tarasenko
2013-04-27 11:44 ` [Qemu-devel] [PATCH 0/3] sparc64 fixes Blue Swirl
3 siblings, 0 replies; 5+ messages in thread
From: Artyom Tarasenko @ 2013-04-27 5:55 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel, Artyom Tarasenko
- clear interrupts only on writing to the interrupt clear registers
- don't overwrite a currently active interrupt request
- use the correct addresses for the interrupt clear registers
(section 19.3.3.3 of the UltraSPARC™-IIi User’s Manual)
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
---
hw/pci-host/apb.c | 114 ++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 96 insertions(+), 18 deletions(-)
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 3bc0d10..356853a 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -2,6 +2,7 @@
* QEMU Ultrasparc APB PCI host
*
* Copyright (c) 2006 Fabrice Bellard
+ * Copyright (c) 2012,2013 Artyom Tarasenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -67,6 +68,7 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
#define RESET_WMASK 0x60000000
#define MAX_IVEC 0x40
+#define NO_IRQ_REQUEST (MAX_IVEC + 1)
typedef struct APBState {
SysBusDevice busdev;
@@ -75,17 +77,64 @@ typedef struct APBState {
MemoryRegion pci_config;
MemoryRegion pci_mmio;
MemoryRegion pci_ioport;
+ uint64_t pci_irq_in;
uint32_t iommu[4];
uint32_t pci_control[16];
uint32_t pci_irq_map[8];
uint32_t obio_irq_map[32];
qemu_irq *pbm_irqs;
qemu_irq *ivec_irqs;
+ unsigned int irq_request;
uint32_t reset_control;
unsigned int nr_resets;
} APBState;
-static void pci_apb_set_irq(void *opaque, int irq_num, int level);
+static inline void pbm_set_request(APBState *s, unsigned int irq_num)
+{
+ APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
+
+ s->irq_request = irq_num;
+ qemu_set_irq(s->ivec_irqs[irq_num], 1);
+}
+
+static inline void pbm_check_irqs(APBState *s)
+{
+
+ unsigned int i;
+
+ /* Previous request is not acknowledged, resubmit */
+ if (s->irq_request != NO_IRQ_REQUEST) {
+ pbm_set_request(s, s->irq_request);
+ return;
+ }
+ /* no request pending */
+ if (s->pci_irq_in == 0ULL) {
+ return;
+ }
+ for (i = 0; i < 32; i++) {
+ if (s->pci_irq_in & (1ULL << i)) {
+ if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
+ pbm_set_request(s, i);
+ return;
+ }
+ }
+ }
+ for (i = 32; i < 64; i++) {
+ if (s->pci_irq_in & (1ULL << i)) {
+ if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
+ pbm_set_request(s, i);
+ break;
+ }
+ }
+ }
+}
+
+static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
+{
+ APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
+ qemu_set_irq(s->ivec_irqs[irq_num], 0);
+ s->irq_request = NO_IRQ_REQUEST;
+}
static void apb_config_writel (void *opaque, hwaddr addr,
uint64_t val, unsigned size)
@@ -105,24 +154,43 @@ static void apb_config_writel (void *opaque, hwaddr addr,
break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
- s->pci_irq_map[(addr & 0x3f) >> 3] &= PBM_PCI_IMR_MASK;
- s->pci_irq_map[(addr & 0x3f) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+ unsigned int ino = (addr & 0x3f) >> 3;
+ s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
+ s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
+ if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
+ pbm_clear_request(s, ino);
+ }
+ pbm_check_irqs(s);
}
break;
case 0x1000 ... 0x1080: /* OBIO interrupt control */
if (addr & 4) {
- s->obio_irq_map[(addr & 0xff) >> 3] &= PBM_PCI_IMR_MASK;
- s->obio_irq_map[(addr & 0xff) >> 3] |= val & ~PBM_PCI_IMR_MASK;
+ unsigned int ino = ((addr & 0xff) >> 3);
+ s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
+ s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
+ if ((s->irq_request == (ino | 0x20))
+ && !(val & ~PBM_PCI_IMR_MASK)) {
+ pbm_clear_request(s, ino | 0x20);
+ }
+ pbm_check_irqs(s);
}
break;
- case 0x1400 ... 0x143f: /* PCI interrupt clear */
+ case 0x1400 ... 0x14ff: /* PCI interrupt clear */
if (addr & 4) {
- pci_apb_set_irq(s, (addr & 0x3f) >> 3, 0);
+ unsigned int ino = (addr & 0xff) >> 5;
+ if ((s->irq_request / 4) == ino) {
+ pbm_clear_request(s, s->irq_request);
+ pbm_check_irqs(s);
+ }
}
break;
case 0x1800 ... 0x1860: /* OBIO interrupt clear */
if (addr & 4) {
- pci_apb_set_irq(s, 0x20 | ((addr & 0xff) >> 3), 0);
+ unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
+ if (s->irq_request == ino) {
+ pbm_clear_request(s, ino);
+ pbm_check_irqs(s);
+ }
}
break;
case 0x2000 ... 0x202f: /* PCI control */
@@ -304,23 +372,28 @@ static void pci_apb_set_irq(void *opaque, int irq_num, int level)
{
APBState *s = opaque;
+ APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
/* PCI IRQ map onto the first 32 INO. */
if (irq_num < 32) {
- if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
- APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
- qemu_set_irq(s->ivec_irqs[irq_num], level);
+ if (level) {
+ s->pci_irq_in |= 1ULL << irq_num;
+ if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
+ pbm_set_request(s, irq_num);
+ }
} else {
- APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
- qemu_irq_lower(s->ivec_irqs[irq_num]);
+ s->pci_irq_in &= ~(1ULL << irq_num);
}
} else {
- /* OBIO IRQ map onto the next 16 INO. */
- if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED) {
+ /* OBIO IRQ map onto the next 32 INO. */
+ if (level) {
APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
- qemu_set_irq(s->ivec_irqs[irq_num], level);
+ s->pci_irq_in |= 1ULL << irq_num;
+ if ((s->irq_request == NO_IRQ_REQUEST)
+ && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
+ pbm_set_request(s, irq_num);
+ }
} else {
- APB_DPRINTF("%s: not enabled: lower irq %d\n", __func__, irq_num);
- qemu_irq_lower(s->ivec_irqs[irq_num]);
+ s->pci_irq_in &= ~(1ULL << irq_num);
}
}
}
@@ -420,6 +493,9 @@ static void pci_pbm_reset(DeviceState *d)
s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
}
+ s->irq_request = NO_IRQ_REQUEST;
+ s->pci_irq_in = 0ULL;
+
if (s->nr_resets++ == 0) {
/* Power on reset */
s->reset_control = POR;
@@ -445,6 +521,8 @@ static int pci_pbm_init_device(SysBusDevice *dev)
s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
}
s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
+ s->irq_request = NO_IRQ_REQUEST;
+ s->pci_irq_in = 0ULL;
/* apb_config */
memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH 3/3] sparc64: use direct interrupt mapping for PCI devices
2013-04-27 5:55 [Qemu-devel] [PATCH 0/3] sparc64 fixes Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 1/3] sparc64: allow 64 IRQ lines Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 2/3] sparc64: fix loosing interrupts Artyom Tarasenko
@ 2013-04-27 5:55 ` Artyom Tarasenko
2013-04-27 11:44 ` [Qemu-devel] [PATCH 0/3] sparc64 fixes Blue Swirl
3 siblings, 0 replies; 5+ messages in thread
From: Artyom Tarasenko @ 2013-04-27 5:55 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel, Artyom Tarasenko
Every PCI Slot in PBM has 4 directly mapped IRQ lines.
Use the IRQ routing schema 0bssnn (Bus, Slot, interrupt Number)
described in Section 19.3.3 of UltraSPARC™-IIi User's Manual.
Please note that this patch requires the OpenBIOS counterpart patch.
Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
---
hw/pci-host/apb.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 356853a..93ce46d 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -365,7 +365,7 @@ static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
bus_offset = 16;
else
bus_offset = 0;
- return bus_offset + irq_num;
+ return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
}
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] sparc64 fixes
2013-04-27 5:55 [Qemu-devel] [PATCH 0/3] sparc64 fixes Artyom Tarasenko
` (2 preceding siblings ...)
2013-04-27 5:55 ` [Qemu-devel] [PATCH 3/3] sparc64: use direct interrupt mapping for PCI devices Artyom Tarasenko
@ 2013-04-27 11:44 ` Blue Swirl
3 siblings, 0 replies; 5+ messages in thread
From: Blue Swirl @ 2013-04-27 11:44 UTC (permalink / raw)
To: Artyom Tarasenko; +Cc: qemu-devel
Thanks, applied all. I fixed the indentation in 2/3 for apb_config_writel().
On Sat, Apr 27, 2013 at 5:55 AM, Artyom Tarasenko <atar4qemu@gmail.com> wrote:
> Various fixes:
> On the real hardware IRQ lines of the PCI bus are not shared.
> In the previous QEMU implementation before this series, all PCI devices
> used the IRQ line 0. Combined with auto-clearing interrupts this made
> the guest OS extremely unstable. The test case is installing
> Debian Wheezy / sparc64:
> http://tyom.blogspot.de/2013/03/debiansparc64-wheezy-under-qemu-how-to.html
> Without the patches the install process hangs at random places between 6% and 60%.
> With this series the installation succeeds.
> Please note that the patch 3/3 requires updating OpenBIOS.
>
> Artyom Tarasenko (3):
> sparc64: allow 64 IRQ lines
> sparc64: fix loosing interrupts
> sparc64: use direct interrupt mapping for PCI devices
>
> hw/pci-host/apb.c | 118 +++++++++++++++++++++++++++++++++++++++++++---------
> hw/sparc64/sun4u.c | 2 +-
> 2 files changed, 99 insertions(+), 21 deletions(-)
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-04-27 11:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-27 5:55 [Qemu-devel] [PATCH 0/3] sparc64 fixes Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 1/3] sparc64: allow 64 IRQ lines Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 2/3] sparc64: fix loosing interrupts Artyom Tarasenko
2013-04-27 5:55 ` [Qemu-devel] [PATCH 3/3] sparc64: use direct interrupt mapping for PCI devices Artyom Tarasenko
2013-04-27 11:44 ` [Qemu-devel] [PATCH 0/3] sparc64 fixes Blue Swirl
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.