From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:36928) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SCazV-0001Tu-AQ for qemu-devel@nongnu.org; Tue, 27 Mar 2012 14:19:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SCazP-00060p-LP for qemu-devel@nongnu.org; Tue, 27 Mar 2012 14:19:32 -0400 Received: from mail-qa0-f46.google.com ([209.85.216.46]:55043) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SCazP-00060Z-Dq for qemu-devel@nongnu.org; Tue, 27 Mar 2012 14:19:27 -0400 Received: by qaeb19 with SMTP id b19so3349177qae.12 for ; Tue, 27 Mar 2012 11:19:25 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: From: Artyom Tarasenko Date: Tue, 27 Mar 2012 20:19:04 +0200 Message-ID: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH 3/3] sparc64: implement PCI and ISA irqs List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Blue Swirl Cc: qemu-devel , "Michael S. Tsirkin" On Sun, Mar 11, 2012 at 12:02 PM, Blue Swirl wrote: > Generate correct trap for external interrupts. Map PCI and ISA IRQs to > RIC/UltraSPARC-IIi interrupt vectors. > > Signed-off-by: Blue Swirl > --- > =A0hw/apb_pci.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 48 ++++++++++++++++++++= +++++++---------- > =A0hw/apb_pci.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 =A03 +- > =A0hw/sun4u.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 57 ++++++++++++++++++= ++++++++++++-------------- > =A0target-sparc/cpu.h =A0 =A0 =A0 =A0 | =A0 =A03 ++ > =A0target-sparc/ldst_helper.c | =A0 20 ++++++++++---- > =A05 files changed, 93 insertions(+), 38 deletions(-) > > diff --git a/hw/apb_pci.c b/hw/apb_pci.c > index b10f31e..7e28808 100644 > --- a/hw/apb_pci.c > +++ b/hw/apb_pci.c > @@ -66,6 +66,8 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0) > =A0#define RESET_WCMASK 0x98000000 > =A0#define RESET_WMASK =A00x60000000 > > +#define MAX_IVEC 0x30 Shouldn't that be 0x40 (0x20 for OBIO and 0x20 for PCI)? I mean in theory, obviously not all of them are used. > + > =A0typedef struct APBState { > =A0 =A0 SysBusDevice busdev; > =A0 =A0 PCIBus =A0 =A0 =A0*bus; > @@ -77,7 +79,8 @@ typedef struct APBState { > =A0 =A0 uint32_t pci_control[16]; > =A0 =A0 uint32_t pci_irq_map[8]; > =A0 =A0 uint32_t obio_irq_map[32]; > - =A0 =A0qemu_irq pci_irqs[32]; > + =A0 =A0qemu_irq *pbm_irqs; > + =A0 =A0qemu_irq *ivec_irqs; > =A0 =A0 uint32_t reset_control; > =A0 =A0 unsigned int nr_resets; > =A0} APBState; > @@ -87,7 +90,7 @@ static void apb_config_writel (void *opaque, > target_phys_addr_t addr, > =A0{ > =A0 =A0 APBState *s =3D opaque; > > - =A0 =A0APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, add= r, val); > + =A0 =A0APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", > __func__, addr, val); > > =A0 =A0 switch (addr & 0xffff) { > =A0 =A0 case 0x30 ... 0x4f: /* DMA error registers */ > @@ -104,6 +107,12 @@ static void apb_config_writel (void *opaque, > target_phys_addr_t addr, > =A0 =A0 =A0 =A0 =A0 =A0 s->pci_irq_map[(addr & 0x3f) >> 3] |=3D val & ~PB= M_PCI_IMR_MASK; > =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 break; > + =A0 =A0case 0x1000 ... 0x1080: /* OBIO interrupt control */ > + =A0 =A0 =A0 =A0if (addr & 4) { > + =A0 =A0 =A0 =A0 =A0 =A0s->obio_irq_map[(addr & 0xff) >> 3] &=3D PBM_PCI= _IMR_MASK; > + =A0 =A0 =A0 =A0 =A0 =A0s->obio_irq_map[(addr & 0xff) >> 3] |=3D val & ~= PBM_PCI_IMR_MASK; > + =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0break; > =A0 =A0 case 0x2000 ... 0x202f: /* PCI control */ > =A0 =A0 =A0 =A0 s->pci_control[(addr & 0x3f) >> 2] =3D val; > =A0 =A0 =A0 =A0 break; > @@ -154,6 +163,13 @@ static uint64_t apb_config_readl (void *opaque, > =A0 =A0 =A0 =A0 =A0 =A0 val =3D 0; > =A0 =A0 =A0 =A0 } > =A0 =A0 =A0 =A0 break; > + =A0 =A0case 0x1000 ... 0x1080: /* OBIO interrupt control */ > + =A0 =A0 =A0 =A0if (addr & 4) { > + =A0 =A0 =A0 =A0 =A0 =A0val =3D s->obio_irq_map[(addr & 0xff) >> 3]; > + =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0val =3D 0; > + =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0break; > =A0 =A0 case 0x2000 ... 0x202f: /* PCI control */ > =A0 =A0 =A0 =A0 val =3D s->pci_control[(addr & 0x3f) >> 2]; > =A0 =A0 =A0 =A0 break; > @@ -190,7 +206,7 @@ static void apb_pci_config_write(void *opaque, > target_phys_addr_t addr, > =A0 =A0 APBState *s =3D opaque; > > =A0 =A0 val =3D qemu_bswap_len(val, size); > - =A0 =A0APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, add= r, val); > + =A0 =A0APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %" PRIx64 "\n", > __func__, addr, val); > =A0 =A0 pci_data_write(s->bus, addr, val, size); > =A0} > > @@ -280,10 +296,19 @@ static void pci_apb_set_irq(void *opaque, int > irq_num, int level) > =A0 =A0 if (irq_num < 32) { > =A0 =A0 =A0 =A0 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) { > =A0 =A0 =A0 =A0 =A0 =A0 APB_DPRINTF("%s: set irq %d level %d\n", __func__= , irq_num, level); > - =A0 =A0 =A0 =A0 =A0 =A0qemu_set_irq(s->pci_irqs[irq_num], level); > + =A0 =A0 =A0 =A0 =A0 =A0qemu_set_irq(s->ivec_irqs[irq_num], level); > + =A0 =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0 =A0 =A0APB_DPRINTF("%s: not enabled: lower irq %d\n", _= _func__, irq_num); > + =A0 =A0 =A0 =A0 =A0 =A0qemu_irq_lower(s->ivec_irqs[irq_num]); > + =A0 =A0 =A0 =A0} > + =A0 =A0} else { > + =A0 =A0 =A0 =A0/* OBIO IRQ map onto the next 16 INO. =A0*/ > + =A0 =A0 =A0 =A0if (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)= { > + =A0 =A0 =A0 =A0 =A0 =A0APB_DPRINTF("%s: set irq %d level %d\n", __func_= _, irq_num, level); > + =A0 =A0 =A0 =A0 =A0 =A0qemu_set_irq(s->ivec_irqs[irq_num], level); > =A0 =A0 =A0 =A0 } else { > =A0 =A0 =A0 =A0 =A0 =A0 APB_DPRINTF("%s: not enabled: lower irq %d\n", __= func__, irq_num); > - =A0 =A0 =A0 =A0 =A0 =A0qemu_irq_lower(s->pci_irqs[irq_num]); > + =A0 =A0 =A0 =A0 =A0 =A0qemu_irq_lower(s->ivec_irqs[irq_num]); > =A0 =A0 =A0 =A0 } > =A0 =A0 } > =A0} > @@ -316,12 +341,12 @@ static int apb_pci_bridge_initfn(PCIDevice *dev) > > =A0PCIBus *pci_apb_init(target_phys_addr_t special_base, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0target_phys_addr_t mem_base, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_irq *pic, PCIBus **bus2, P= CIBus **bus3) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_irq *ivec_irqs, PCIBus **b= us2, PCIBus **bus3, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_irq **pbm_irqs) > =A0{ > =A0 =A0 DeviceState *dev; > =A0 =A0 SysBusDevice *s; > =A0 =A0 APBState *d; > - =A0 =A0unsigned int i; > =A0 =A0 PCIDevice *pci_dev; > =A0 =A0 PCIBridge *br; > > @@ -346,9 +371,8 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 get_system_io= (), > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0, 32); > > - =A0 =A0for (i =3D 0; i < 32; i++) { > - =A0 =A0 =A0 =A0sysbus_connect_irq(s, i, pic[i]); > - =A0 =A0} > + =A0 =A0*pbm_irqs =3D d->pbm_irqs; > + =A0 =A0d->ivec_irqs =3D ivec_irqs; > > =A0 =A0 pci_create_simple(d->bus, 0, "pbm-pci"); > > @@ -402,9 +426,7 @@ static int pci_pbm_init_device(SysBusDevice *dev) > =A0 =A0 for (i =3D 0; i < 8; i++) { > =A0 =A0 =A0 =A0 s->pci_irq_map[i] =3D (0x1f << 6) | (i << 2); > =A0 =A0 } > - =A0 =A0for (i =3D 0; i < 32; i++) { > - =A0 =A0 =A0 =A0sysbus_init_irq(dev, &s->pci_irqs[i]); > - =A0 =A0} > + =A0 =A0s->pbm_irqs =3D qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC)= ; > > =A0 =A0 /* apb_config */ > =A0 =A0 memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-co= nfig", > diff --git a/hw/apb_pci.h b/hw/apb_pci.h > index 8869f9d..55f7c4c 100644 > --- a/hw/apb_pci.h > +++ b/hw/apb_pci.h > @@ -5,5 +5,6 @@ > > =A0PCIBus *pci_apb_init(target_phys_addr_t special_base, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0target_phys_addr_t mem_base, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_irq *pic, PCIBus **bus2, P= CIBus **bus3); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_irq *ivec_irqs, PCIBus **b= us2, PCIBus **bus3, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_irq **pbm_irqs); > =A0#endif > diff --git a/hw/sun4u.c b/hw/sun4u.c > index 423108f..e0adb9e 100644 > --- a/hw/sun4u.c > +++ b/hw/sun4u.c > @@ -81,7 +81,7 @@ > =A0#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) > =A0#define FW_CFG_SPARC64_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) > > -#define MAX_PILS 16 > +#define IVEC_MAX =A0 =A0 =A0 =A0 =A0 =A0 0x30 > > =A0#define TICK_MAX =A0 =A0 =A0 =A0 =A0 =A0 0x7fffffffffffffffULL > > @@ -304,18 +304,24 @@ static void cpu_kick_irq(CPUState *env) > =A0 =A0 qemu_cpu_kick(env); > =A0} > > -static void cpu_set_irq(void *opaque, int irq, int level) > +static void cpu_set_ivec_irq(void *opaque, int irq, int level) > =A0{ > =A0 =A0 CPUState *env =3D opaque; > > =A0 =A0 if (level) { > - =A0 =A0 =A0 =A0CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq); > - =A0 =A0 =A0 =A0env->pil_in |=3D 1 << irq; > - =A0 =A0 =A0 =A0cpu_kick_irq(env); > - =A0 =A0} else { > - =A0 =A0 =A0 =A0CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq); > - =A0 =A0 =A0 =A0env->pil_in &=3D ~(1 << irq); > - =A0 =A0 =A0 =A0cpu_check_irqs(env); > + =A0 =A0 =A0 =A0CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq); > + =A0 =A0 =A0 =A0env->interrupt_index =3D TT_IVEC; > + =A0 =A0 =A0 =A0env->pil_in |=3D 1 << 5; Err. Spurious irq 5? > + =A0 =A0 =A0 =A0env->ivec_status |=3D 0x20; > + =A0 =A0 =A0 =A0env->ivec_data[0] =3D (0x1f << 6) | irq; > + =A0 =A0 =A0 =A0env->ivec_data[1] =3D 0; > + =A0 =A0 =A0 =A0env->ivec_data[2] =3D 0; > + =A0 =A0 =A0 =A0cpu_interrupt(env, CPU_INTERRUPT_HARD); Shouldn't there be a cpu_interrupts_enabled(env) check before? > + =A0 =A0 =A0} else { > + =A0 =A0 =A0 =A0CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq); > + =A0 =A0 =A0 =A0env->pil_in &=3D ~(1 << 5); > + =A0 =A0 =A0 =A0env->ivec_status &=3D ~0x20; > + =A0 =A0 =A0 =A0cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); > =A0 =A0 } > =A0} > > @@ -521,13 +527,29 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t l= imit) > =A0 =A0 } > =A0} > > -static void dummy_isa_irq_handler(void *opaque, int n, int level) > +static void isa_irq_handler(void *opaque, int n, int level) > =A0{ > + =A0 =A0static const int isa_irq_to_ivec[16] =3D { > + =A0 =A0 =A0 =A0[1] =3D 0x29, /* keyboard */ > + =A0 =A0 =A0 =A0[4] =3D 0x2b, /* serial */ > + =A0 =A0 =A0 =A0[6] =3D 0x27, /* floppy */ > + =A0 =A0 =A0 =A0[7] =3D 0x22, /* parallel */ > + =A0 =A0 =A0 =A0[12] =3D 0x2a, /* mouse */ > + =A0 =A0}; > + =A0 =A0qemu_irq *irqs =3D opaque; > + =A0 =A0int ivec; > + > + =A0 =A0assert(n < 16); > + =A0 =A0ivec =3D isa_irq_to_ivec[n]; > + =A0 =A0EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level,= ivec); > + =A0 =A0if (ivec) { > + =A0 =A0 =A0 =A0qemu_set_irq(irqs[ivec], level); > + =A0 =A0} > =A0} > > =A0/* EBUS (Eight bit bus) bridge */ > =A0static ISABus * > -pci_ebus_init(PCIBus *bus, int devfn) > +pci_ebus_init(PCIBus *bus, int devfn, qemu_irq *irqs) > =A0{ > =A0 =A0 qemu_irq *isa_irq; > =A0 =A0 PCIDevice *pci_dev; > @@ -536,7 +558,7 @@ pci_ebus_init(PCIBus *bus, int devfn) > =A0 =A0 pci_dev =3D pci_create_simple(bus, devfn, "ebus"); > =A0 =A0 isa_bus =3D DO_UPCAST(ISABus, qbus, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qdev_get_child_bus(&pci_d= ev->qdev, "isa.0")); > - =A0 =A0isa_irq =3D qemu_allocate_irqs(dummy_isa_irq_handler, NULL, 16); > + =A0 =A0isa_irq =3D qemu_allocate_irqs(isa_irq_handler, irqs, 16); > =A0 =A0 isa_bus_irqs(isa_bus, isa_irq); > =A0 =A0 return isa_bus; > =A0} > @@ -761,7 +783,7 @@ static void sun4uv_init(MemoryRegion *address_space_m= em, > =A0 =A0 long initrd_size, kernel_size; > =A0 =A0 PCIBus *pci_bus, *pci_bus2, *pci_bus3; > =A0 =A0 ISABus *isa_bus; > - =A0 =A0qemu_irq *irq; > + =A0 =A0qemu_irq *ivec_irqs, *pbm_irqs; > =A0 =A0 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; > =A0 =A0 DriveInfo *fd[MAX_FD]; > =A0 =A0 void *fw_cfg; > @@ -774,14 +796,13 @@ static void sun4uv_init(MemoryRegion *address_space= _mem, > > =A0 =A0 prom_init(hwdef->prom_addr, bios_name); > > - > - =A0 =A0irq =3D qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); > - =A0 =A0pci_bus =3D pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &p= ci_bus2, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &pci_bus3); > + =A0 =A0ivec_irqs =3D qemu_allocate_irqs(cpu_set_ivec_irq, env, IVEC_MAX= ); > + =A0 =A0pci_bus =3D pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_ir= qs, > &pci_bus2, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &pci_bus3, &pbm_irq= s); > =A0 =A0 pci_vga_init(pci_bus); > > =A0 =A0 // XXX Should be pci_bus3 > - =A0 =A0isa_bus =3D pci_ebus_init(pci_bus, -1); > + =A0 =A0isa_bus =3D pci_ebus_init(pci_bus, -1, pbm_irqs); > > =A0 =A0 i =3D 0; > =A0 =A0 if (hwdef->console_serial_base) { > diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h > index b81779b..8994000 100644 > --- a/target-sparc/cpu.h > +++ b/target-sparc/cpu.h > @@ -491,6 +491,9 @@ typedef struct CPUSPARCState { > =A0 =A0 /* UA 2005 hyperprivileged registers */ > =A0 =A0 uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_c= mpr, ssr; > =A0 =A0 CPUTimer *hstick; // UA 2005 > + =A0 =A0/* Interrupt vector registers */ > + =A0 =A0uint64_t ivec_status; > + =A0 =A0uint64_t ivec_data[3]; > =A0 =A0 uint32_t softint; > =A0#define SOFTINT_TIMER =A0 1 > =A0#define SOFTINT_STIMER =A0(1 << 16) > diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c > index b59707e..4c34346 100644 > --- a/target-sparc/ldst_helper.c > +++ b/target-sparc/ldst_helper.c > @@ -1526,6 +1526,19 @@ uint64_t helper_ld_asi(target_ulong addr, int > asi, int size, int sign) > =A0 =A0 =A0 =A0 =A0 =A0 ret =3D env->dtlb[reg].tag; > =A0 =A0 =A0 =A0 =A0 =A0 break; > =A0 =A0 =A0 =A0 } > + =A0 =A0case 0x48: /* Interrupt dispatch, RO */ > + =A0 =A0 =A0 =A0break; > + =A0 =A0case 0x49: /* Interrupt data receive */ > + =A0 =A0 =A0 =A0ret =3D env->ivec_status; > + =A0 =A0 =A0 =A0break; > + =A0 =A0case 0x7f: /* Incoming interrupt vector, RO */ > + =A0 =A0 =A0 =A0{ > + =A0 =A0 =A0 =A0 =A0 =A0int reg =3D (addr >> 4) & 0x3; > + =A0 =A0 =A0 =A0 =A0 =A0if (reg < 3) { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D env->ivec_data[reg]; > + =A0 =A0 =A0 =A0 =A0 =A0} > + =A0 =A0 =A0 =A0 =A0 =A0break; > + =A0 =A0 =A0 =A0} > =A0 =A0 case 0x46: /* D-cache data */ > =A0 =A0 case 0x47: /* D-cache tag access */ > =A0 =A0 case 0x4b: /* E-cache error enable */ > @@ -1540,11 +1553,6 @@ uint64_t helper_ld_asi(target_ulong addr, int > asi, int size, int sign) > =A0 =A0 case 0x7e: /* E-cache tag */ > =A0 =A0 =A0 =A0 break; > =A0 =A0 case 0x5b: /* D-MMU data pointer */ > - =A0 =A0case 0x48: /* Interrupt dispatch, RO */ > - =A0 =A0case 0x49: /* Interrupt data receive */ > - =A0 =A0case 0x7f: /* Incoming interrupt vector, RO */ > - =A0 =A0 =A0 =A0/* XXX */ > - =A0 =A0 =A0 =A0break; > =A0 =A0 case 0x54: /* I-MMU data in, WO */ > =A0 =A0 case 0x57: /* I-MMU demap, WO */ > =A0 =A0 case 0x5c: /* D-MMU data in, WO */ > @@ -1954,7 +1962,7 @@ void helper_st_asi(target_ulong addr, > target_ulong val, int asi, int size) > =A0 =A0 =A0 =A0 demap_tlb(env->dtlb, addr, "dmmu", env); > =A0 =A0 =A0 =A0 return; > =A0 =A0 case 0x49: /* Interrupt data receive */ > - =A0 =A0 =A0 =A0/* XXX */ > + =A0 =A0 =A0 =A0env->ivec_status =3D val & 0x20; > =A0 =A0 =A0 =A0 return; > =A0 =A0 case 0x46: /* D-cache data */ > =A0 =A0 case 0x47: /* D-cache tag access */ > -- > 1.7.9 --=20 Regards, Artyom Tarasenko solaris/sparc under qemu blog: http://tyom.blogspot.com/search/label/qemu