From 0374cbd2f1b5bc68816c811bdaf266d98b21ecfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 11 Oct 2020 17:18:59 +0200 Subject: [PATCH 01/35] hw/pci-host: Use the PCI_BUILD_BDF() macro from 'hw/pci/pci.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have a generic PCI_BUILD_BDF() macro in "hw/pci/pci.h" to pack these values, use it. Signed-off-by: Philippe Mathieu-Daudé Acked-by: David Gibson Acked-by: Michael S. Tsirkin Message-Id: <20201012124506.3406909-3-philmd@redhat.com> --- hw/pci-host/bonito.c | 3 +-- hw/pci-host/pnv_phb4.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index a99eced065..b05295639a 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -196,8 +196,7 @@ FIELD(BONGENCFG, PCIQUEUE, 12, 1) #define PCI_IDSEL_VIA686B (1 << PCI_IDSEL_VIA686B_BIT) #define PCI_ADDR(busno , devno , funno , regno) \ - ((((busno) << 16) & 0xff0000) + (((devno) << 11) & 0xf800) + \ - (((funno) << 8) & 0x700) + (regno)) + ((PCI_BUILD_BDF(busno, PCI_DEVFN(devno , funno)) << 8) + (regno)) typedef struct BonitoState BonitoState; diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 03daf40a23..6328e985f8 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -889,7 +889,7 @@ static bool pnv_phb4_resolve_pe(PnvPhb4DMASpace *ds) /* Read RTE */ bus_num = pci_bus_num(ds->bus); addr = rtt & PHB_RTT_BASE_ADDRESS_MASK; - addr += 2 * ((bus_num << 8) | ds->devfn); + addr += 2 * PCI_BUILD_BDF(bus_num, ds->devfn); if (dma_memory_read(&address_space_memory, addr, &rte, sizeof(rte))) { phb_error(ds->phb, "Failed to read RTT entry at 0x%"PRIx64, addr); /* Set error bits ? fence ? ... */ From d08b9c1b75c60c66ea65212a9dac90f58542e45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 11 Oct 2020 17:22:04 +0200 Subject: [PATCH 02/35] hw/pci-host/uninorth: Use the PCI_FUNC() macro from 'hw/pci/pci.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have a generic PCI_FUNC() macro in "hw/pci/pci.h" to extract the PCI function identifier, use it. Signed-off-by: Philippe Mathieu-Daudé Acked-by: David Gibson Acked-by: Michael S. Tsirkin Message-Id: <20201012124506.3406909-4-philmd@redhat.com> --- hw/pci-host/uninorth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index 0c0a9ecee1..f0a4d8c717 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -63,7 +63,7 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) if (slot == 32) { slot = -1; /* XXX: should this be 0? */ } - func = (reg >> 8) & 7; + func = PCI_FUNC(reg >> 8); /* ... and then convert them to x86 format */ /* config pointer */ From 8d40def66d744a964c2675a19c11f644d288dd4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 11 Oct 2020 17:04:23 +0200 Subject: [PATCH 03/35] hw: Use the PCI_SLOT() macro from 'hw/pci/pci.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have a generic PCI_SLOT() macro in "hw/pci/pci.h" to extract the PCI slot identifier, use it. Signed-off-by: Philippe Mathieu-Daudé Acked-by: Paul Durrant Acked-by: David Gibson Acked-by: Michael S. Tsirkin Message-Id: <20201012124506.3406909-5-philmd@redhat.com> --- hw/hppa/dino.c | 2 +- hw/i386/xen/xen-hvm.c | 2 +- hw/isa/piix3.c | 2 +- hw/mips/gt64xxx_pci.c | 2 +- hw/pci-host/bonito.c | 2 +- hw/pci-host/ppce500.c | 2 +- hw/ppc/ppc4xx_pci.c | 2 +- hw/sh4/sh_pci.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/hppa/dino.c b/hw/hppa/dino.c index 81053b5fb6..5b82c9440d 100644 --- a/hw/hppa/dino.c +++ b/hw/hppa/dino.c @@ -496,7 +496,7 @@ static void dino_set_irq(void *opaque, int irq, int level) static int dino_pci_map_irq(PCIDevice *d, int irq_num) { - int slot = d->devfn >> 3; + int slot = PCI_SLOT(d->devfn); assert(irq_num >= 0 && irq_num <= 3); diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 096c46fef1..68821d90f5 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -140,7 +140,7 @@ typedef struct XenIOState { int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) { - return irq_num + ((pci_dev->devfn >> 3) << 2); + return irq_num + (PCI_SLOT(pci_dev->devfn) << 2); } void xen_piix3_set_irq(void *opaque, int irq_num, int level) diff --git a/hw/isa/piix3.c b/hw/isa/piix3.c index 587850b888..f46ccae25c 100644 --- a/hw/isa/piix3.c +++ b/hw/isa/piix3.c @@ -361,7 +361,7 @@ type_init(piix3_register_types) static int pci_slot_get_pirq(PCIDevice *pci_dev, int pci_intx) { int slot_addend; - slot_addend = (pci_dev->devfn >> 3) - 1; + slot_addend = PCI_SLOT(pci_dev->devfn) - 1; return (pci_intx + slot_addend) & 3; } diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index e091bc4ed5..588e6f9930 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -982,7 +982,7 @@ static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num) { int slot; - slot = (pci_dev->devfn >> 3); + slot = PCI_SLOT(pci_dev->devfn); switch (slot) { /* PIIX4 USB */ diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index b05295639a..ee8b193e15 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -570,7 +570,7 @@ static int pci_bonito_map_irq(PCIDevice *pci_dev, int irq_num) { int slot; - slot = (pci_dev->devfn >> 3); + slot = PCI_SLOT(pci_dev->devfn); switch (slot) { case 5: /* FULOONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */ diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index 9517aab913..5ad1424b31 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -342,7 +342,7 @@ static const MemoryRegionOps e500_pci_reg_ops = { static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int pin) { - int devno = pci_dev->devfn >> 3; + int devno = PCI_SLOT(pci_dev->devfn); int ret; ret = ppce500_pci_map_irq_slot(devno, pin); diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 28724c06f8..e8789f64e8 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -243,7 +243,7 @@ static void ppc4xx_pci_reset(void *opaque) * may need further refactoring for other boards. */ static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num) { - int slot = pci_dev->devfn >> 3; + int slot = PCI_SLOT(pci_dev->devfn); trace_ppc4xx_pci_map_irq(pci_dev->devfn, irq_num, slot); diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index 73d2d0bccb..734892f47c 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -109,7 +109,7 @@ static const MemoryRegionOps sh_pci_reg_ops = { static int sh_pci_map_irq(PCIDevice *d, int irq_num) { - return (d->devfn >> 3); + return PCI_SLOT(d->devfn); } static void sh_pci_set_irq(void *opaque, int irq_num, int level) From 4934e479f1806e69cfab637156fe136994619c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 12 Oct 2020 08:36:41 +0200 Subject: [PATCH 04/35] hw: Use the PCI_DEVFN() macro from 'hw/pci/pci.h' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have a generic PCI_DEVFN() macro in "hw/pci/pci.h" to pack the PCI slot/function identifiers, use it. Signed-off-by: Philippe Mathieu-Daudé Acked-by: David Gibson Message-Id: <20201012124506.3406909-6-philmd@redhat.com> Reviewed-by: Huacai Chen Acked-by: Michael S. Tsirkin Message-Id: <20201231224911.1467352-4-f4bug@amsat.org> --- hw/arm/virt.c | 3 ++- hw/pci-host/bonito.c | 2 +- hw/pci-host/uninorth.c | 6 ++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 96985917d3..bf3a717111 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1147,7 +1147,8 @@ static void create_pcie_irq_map(const VirtMachineState *vms, full_irq_map, sizeof(full_irq_map)); qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupt-map-mask", - 0x1800, 0, 0, /* devfn (PCI_SLOT(3)) */ + cpu_to_be16(PCI_DEVFN(3, 0)), /* Slot 3 */ + 0, 0, 0x7 /* PCI irq */); } diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index ee8b193e15..40dda237d8 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -631,7 +631,7 @@ static void bonito_pcihost_realize(DeviceState *dev, Error **errp) phb->bus = pci_register_root_bus(dev, "pci", pci_bonito_set_irq, pci_bonito_map_irq, dev, &bs->pci_mem, get_system_io(), - 0x28, 32, TYPE_PCI_BUS); + PCI_DEVFN(5, 0), 32, TYPE_PCI_BUS); for (size_t i = 0; i < 3; i++) { char *name = g_strdup_printf("pci.lomem%zu", i); diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index f0a4d8c717..d25b62d6a5 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -68,10 +68,8 @@ static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) /* ... and then convert them to x86 format */ /* config pointer */ retval = (reg & (0xff - 7)) | (addr & 7); - /* slot */ - retval |= slot << 11; - /* fn */ - retval |= func << 8; + /* slot, fn */ + retval |= PCI_DEVFN(slot, func) << 8; } trace_unin_get_config_reg(reg, addr, retval); From ce3f3d3027078939f2b38cd0d371d44ba8a29026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 31 Dec 2020 21:33:55 +0100 Subject: [PATCH 05/35] hw/pci-host/bonito: Display hexadecimal value with '0x' prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Huacai Chen Message-Id: <20201231224911.1467352-3-f4bug@amsat.org> --- hw/pci-host/bonito.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 40dda237d8..c2f71e5a13 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -468,8 +468,8 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr) regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET; if (idsel == 0) { - error_report("error in bonito pci config address " TARGET_FMT_plx - ",pcimap_cfg=%x", addr, s->regs[BONITO_PCIMAP_CFG]); + error_report("error in bonito pci config address 0x" TARGET_FMT_plx + ",pcimap_cfg=0x%x", addr, s->regs[BONITO_PCIMAP_CFG]); exit(1); } pciaddr = PCI_ADDR(pci_bus_num(phb->bus), devno, funno, regno); From b4bb339b3ddb24601b5f914fb0bc7275a69d2c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 31 Dec 2020 22:04:13 +0100 Subject: [PATCH 06/35] hw/pci-host/bonito: Use pci_config_set_interrupt_pin() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace pci_set_byte(PCI_INTERRUPT_PIN) by pci_config_set_interrupt_pin(). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Huacai Chen Message-Id: <20201231224911.1467352-5-f4bug@amsat.org> --- hw/pci-host/bonito.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index c2f71e5a13..2a2db7cea6 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -728,7 +728,8 @@ static void bonito_realize(PCIDevice *dev, Error **errp) pci_set_word(dev->config + PCI_SUBSYSTEM_ID, 0x0000); pci_set_byte(dev->config + PCI_INTERRUPT_LINE, 0x00); - pci_set_byte(dev->config + PCI_INTERRUPT_PIN, 0x01); + pci_config_set_interrupt_pin(dev->config, 0x01); /* interrupt pin A */ + pci_set_byte(dev->config + PCI_MIN_GNT, 0x3c); pci_set_byte(dev->config + PCI_MAX_LAT, 0x00); From 5a4856ed78e8b83f6eece2efbbedccba857aaff7 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 07/35] vt82c686: Rename AC97/MC97 parts from VT82C686B to VIA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These parts are common between VT82C686B and VT8231 so can be shared in the future. Rename them to VIA prefix accordingly. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <510ddb17836a2c2e68a27cf2dcaee420bc2efbc1.1609584215.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index b3170c70c3..2a0f85dea9 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -168,22 +168,22 @@ struct VT686PMState { uint32_t smb_io_base; }; -struct VT686AC97State { +struct VIAAC97State { PCIDevice dev; }; -struct VT686MC97State { +struct VIAMC97State { PCIDevice dev; }; #define TYPE_VT82C686B_PM_DEVICE "VT82C686B_PM" OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM_DEVICE) -#define TYPE_VT82C686B_MC97_DEVICE "VT82C686B_MC97" -OBJECT_DECLARE_SIMPLE_TYPE(VT686MC97State, VT82C686B_MC97_DEVICE) +#define TYPE_VIA_MC97_DEVICE "VIA_MC97" +OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97_DEVICE) -#define TYPE_VT82C686B_AC97_DEVICE "VT82C686B_AC97" -OBJECT_DECLARE_SIMPLE_TYPE(VT686AC97State, VT82C686B_AC97_DEVICE) +#define TYPE_VIA_AC97_DEVICE "VIA_AC97" +OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97_DEVICE) static void pm_update_sci(VT686PMState *s) { @@ -260,7 +260,7 @@ static const VMStateDescription vmstate_acpi = { static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp) { - VT686AC97State *s = VT82C686B_AC97_DEVICE(dev); + VIAAC97State *s = VIA_AC97_DEVICE(dev); uint8_t *pci_conf = s->dev.config; pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | @@ -274,7 +274,7 @@ void vt82c686b_ac97_init(PCIBus *bus, int devfn) { PCIDevice *dev; - dev = pci_new(devfn, TYPE_VT82C686B_AC97_DEVICE); + dev = pci_new(devfn, TYPE_VIA_AC97_DEVICE); pci_realize_and_unref(dev, bus, &error_fatal); } @@ -293,9 +293,9 @@ static void via_ac97_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_ac97_info = { - .name = TYPE_VT82C686B_AC97_DEVICE, + .name = TYPE_VIA_AC97_DEVICE, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VT686AC97State), + .instance_size = sizeof(VIAAC97State), .class_init = via_ac97_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, @@ -305,7 +305,7 @@ static const TypeInfo via_ac97_info = { static void vt82c686b_mc97_realize(PCIDevice *dev, Error **errp) { - VT686MC97State *s = VT82C686B_MC97_DEVICE(dev); + VIAMC97State *s = VIA_MC97_DEVICE(dev); uint8_t *pci_conf = s->dev.config; pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | @@ -318,7 +318,7 @@ void vt82c686b_mc97_init(PCIBus *bus, int devfn) { PCIDevice *dev; - dev = pci_new(devfn, TYPE_VT82C686B_MC97_DEVICE); + dev = pci_new(devfn, TYPE_VIA_MC97_DEVICE); pci_realize_and_unref(dev, bus, &error_fatal); } @@ -337,9 +337,9 @@ static void via_mc97_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_mc97_info = { - .name = TYPE_VT82C686B_MC97_DEVICE, + .name = TYPE_VIA_MC97_DEVICE, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VT686MC97State), + .instance_size = sizeof(VIAMC97State), .class_init = via_mc97_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, From e634050544198545ded4b0a324d2e4c7f8c69809 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 08/35] vt82c686: Remove unnecessary _DEVICE suffix from type macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no reason to suffix everything with _DEVICE when the names are already unique without it and shorter names are more readable. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 48 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 2a0f85dea9..1be1169f83 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -49,8 +49,8 @@ struct VT82C686BState { SuperIOConfig superio_conf; }; -#define TYPE_VT82C686B_DEVICE "VT82C686B" -OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BState, VT82C686B_DEVICE) +#define TYPE_VT82C686B "VT82C686B" +OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BState, VT82C686B) static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, unsigned size) @@ -117,7 +117,7 @@ static const MemoryRegionOps superio_ops = { static void vt82c686b_isa_reset(DeviceState *dev) { - VT82C686BState *vt82c = VT82C686B_DEVICE(dev); + VT82C686BState *vt82c = VT82C686B(dev); uint8_t *pci_conf = vt82c->dev.config; pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); @@ -146,7 +146,7 @@ static void vt82c686b_isa_reset(DeviceState *dev) static void vt82c686b_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len) { - VT82C686BState *vt686 = VT82C686B_DEVICE(d); + VT82C686BState *vt686 = VT82C686B(d); DPRINTF("vt82c686b_write_config address 0x%x val 0x%x len 0x%x\n", address, val, len); @@ -176,14 +176,14 @@ struct VIAMC97State { PCIDevice dev; }; -#define TYPE_VT82C686B_PM_DEVICE "VT82C686B_PM" -OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM_DEVICE) +#define TYPE_VT82C686B_PM "VT82C686B_PM" +OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) -#define TYPE_VIA_MC97_DEVICE "VIA_MC97" -OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97_DEVICE) +#define TYPE_VIA_MC97 "VIA_MC97" +OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97) -#define TYPE_VIA_AC97_DEVICE "VIA_AC97" -OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97_DEVICE) +#define TYPE_VIA_AC97 "VIA_AC97" +OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97) static void pm_update_sci(VT686PMState *s) { @@ -260,7 +260,7 @@ static const VMStateDescription vmstate_acpi = { static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp) { - VIAAC97State *s = VIA_AC97_DEVICE(dev); + VIAAC97State *s = VIA_AC97(dev); uint8_t *pci_conf = s->dev.config; pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | @@ -274,7 +274,7 @@ void vt82c686b_ac97_init(PCIBus *bus, int devfn) { PCIDevice *dev; - dev = pci_new(devfn, TYPE_VIA_AC97_DEVICE); + dev = pci_new(devfn, TYPE_VIA_AC97); pci_realize_and_unref(dev, bus, &error_fatal); } @@ -293,7 +293,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_ac97_info = { - .name = TYPE_VIA_AC97_DEVICE, + .name = TYPE_VIA_AC97, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(VIAAC97State), .class_init = via_ac97_class_init, @@ -305,7 +305,7 @@ static const TypeInfo via_ac97_info = { static void vt82c686b_mc97_realize(PCIDevice *dev, Error **errp) { - VIAMC97State *s = VIA_MC97_DEVICE(dev); + VIAMC97State *s = VIA_MC97(dev); uint8_t *pci_conf = s->dev.config; pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | @@ -318,7 +318,7 @@ void vt82c686b_mc97_init(PCIBus *bus, int devfn) { PCIDevice *dev; - dev = pci_new(devfn, TYPE_VIA_MC97_DEVICE); + dev = pci_new(devfn, TYPE_VIA_MC97); pci_realize_and_unref(dev, bus, &error_fatal); } @@ -337,7 +337,7 @@ static void via_mc97_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_mc97_info = { - .name = TYPE_VIA_MC97_DEVICE, + .name = TYPE_VIA_MC97, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(VIAMC97State), .class_init = via_mc97_class_init, @@ -350,7 +350,7 @@ static const TypeInfo via_mc97_info = { /* vt82c686 pm init */ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) { - VT686PMState *s = VT82C686B_PM_DEVICE(dev); + VT686PMState *s = VT82C686B_PM(dev); uint8_t *pci_conf; pci_conf = s->dev.config; @@ -386,10 +386,10 @@ I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, PCIDevice *dev; VT686PMState *s; - dev = pci_new(devfn, TYPE_VT82C686B_PM_DEVICE); + dev = pci_new(devfn, TYPE_VT82C686B_PM); qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base); - s = VT82C686B_PM_DEVICE(dev); + s = VT82C686B_PM(dev); pci_realize_and_unref(dev, bus, &error_fatal); @@ -419,7 +419,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_pm_info = { - .name = TYPE_VT82C686B_PM_DEVICE, + .name = TYPE_VT82C686B_PM, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(VT686PMState), .class_init = via_pm_class_init, @@ -442,7 +442,7 @@ static const VMStateDescription vmstate_via = { /* init the PCI-to-ISA bridge */ static void vt82c686b_realize(PCIDevice *d, Error **errp) { - VT82C686BState *vt82c = VT82C686B_DEVICE(d); + VT82C686BState *vt82c = VT82C686B(d); uint8_t *pci_conf; ISABus *isa_bus; uint8_t *wmask; @@ -479,9 +479,7 @@ ISABus *vt82c686b_isa_init(PCIBus *bus, int devfn) { PCIDevice *d; - d = pci_create_simple_multifunction(bus, devfn, true, - TYPE_VT82C686B_DEVICE); - + d = pci_create_simple_multifunction(bus, devfn, true, TYPE_VT82C686B); return ISA_BUS(qdev_get_child_bus(DEVICE(d), "isa.0")); } @@ -507,7 +505,7 @@ static void via_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_info = { - .name = TYPE_VT82C686B_DEVICE, + .name = TYPE_VT82C686B, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(VT82C686BState), .class_init = via_class_init, From 0f79846147faf87ef17436d4255241ad32cc634c Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 09/35] vt82c686: Rename VT82C686B to VT82C686B_ISA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is really the ISA bridge part so name the type accordingly. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <78db2ced4b41a8a775dbc6c97a90db683952c2cb.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 1be1169f83..d40599c7da 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -43,14 +43,14 @@ typedef struct SuperIOConfig { uint8_t data; } SuperIOConfig; -struct VT82C686BState { +struct VT82C686BISAState { PCIDevice dev; MemoryRegion superio; SuperIOConfig superio_conf; }; -#define TYPE_VT82C686B "VT82C686B" -OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BState, VT82C686B) +#define TYPE_VT82C686B_ISA "vt82c686b-isa" +OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, unsigned size) @@ -117,7 +117,7 @@ static const MemoryRegionOps superio_ops = { static void vt82c686b_isa_reset(DeviceState *dev) { - VT82C686BState *vt82c = VT82C686B(dev); + VT82C686BISAState *vt82c = VT82C686B_ISA(dev); uint8_t *pci_conf = vt82c->dev.config; pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); @@ -146,7 +146,7 @@ static void vt82c686b_isa_reset(DeviceState *dev) static void vt82c686b_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len) { - VT82C686BState *vt686 = VT82C686B(d); + VT82C686BISAState *vt686 = VT82C686B_ISA(d); DPRINTF("vt82c686b_write_config address 0x%x val 0x%x len 0x%x\n", address, val, len); @@ -434,7 +434,7 @@ static const VMStateDescription vmstate_via = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(dev, VT82C686BState), + VMSTATE_PCI_DEVICE(dev, VT82C686BISAState), VMSTATE_END_OF_LIST() } }; @@ -442,7 +442,7 @@ static const VMStateDescription vmstate_via = { /* init the PCI-to-ISA bridge */ static void vt82c686b_realize(PCIDevice *d, Error **errp) { - VT82C686BState *vt82c = VT82C686B(d); + VT82C686BISAState *vt82c = VT82C686B_ISA(d); uint8_t *pci_conf; ISABus *isa_bus; uint8_t *wmask; @@ -479,7 +479,7 @@ ISABus *vt82c686b_isa_init(PCIBus *bus, int devfn) { PCIDevice *d; - d = pci_create_simple_multifunction(bus, devfn, true, TYPE_VT82C686B); + d = pci_create_simple_multifunction(bus, devfn, true, TYPE_VT82C686B_ISA); return ISA_BUS(qdev_get_child_bus(DEVICE(d), "isa.0")); } @@ -505,9 +505,9 @@ static void via_class_init(ObjectClass *klass, void *data) } static const TypeInfo via_info = { - .name = TYPE_VT82C686B, + .name = TYPE_VT82C686B_ISA, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VT82C686BState), + .instance_size = sizeof(VT82C686BISAState), .class_init = via_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, From 07c6832cb2c65407e312e8bed893bf8d7ae770e6 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 10/35] vt82c686: Remove vt82c686b_[am]c97_init() functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are legacy init functions that are just equivalent to directly calling pci_create_simple so do that instead. Also rename objects to lower case via-ac97 and via-mc97 matching naming of other devices. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <1c4373c8aeb6c4fb2a8df2c864b0e91a977a3d7b.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 27 ++++----------------------- hw/mips/fuloong2e.c | 4 ++-- include/hw/isa/vt82c686.h | 4 ++-- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index d40599c7da..8677a2d212 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -179,12 +179,6 @@ struct VIAMC97State { #define TYPE_VT82C686B_PM "VT82C686B_PM" OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) -#define TYPE_VIA_MC97 "VIA_MC97" -OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97) - -#define TYPE_VIA_AC97 "VIA_AC97" -OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97) - static void pm_update_sci(VT686PMState *s) { int sci_level, pmsts; @@ -254,10 +248,13 @@ static const VMStateDescription vmstate_acpi = { }; /* - * TODO: vt82c686b_ac97_init() and vt82c686b_mc97_init() + * TODO: VIA_AC97 and VIA_MC97 * just register a PCI device now, functionalities will be implemented later. */ +OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97) +OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97) + static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp) { VIAAC97State *s = VIA_AC97(dev); @@ -270,14 +267,6 @@ static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp) pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); } -void vt82c686b_ac97_init(PCIBus *bus, int devfn) -{ - PCIDevice *dev; - - dev = pci_new(devfn, TYPE_VIA_AC97); - pci_realize_and_unref(dev, bus, &error_fatal); -} - static void via_ac97_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -314,14 +303,6 @@ static void vt82c686b_mc97_realize(PCIDevice *dev, Error **errp) pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); } -void vt82c686b_mc97_init(PCIBus *bus, int devfn) -{ - PCIDevice *dev; - - dev = pci_new(devfn, TYPE_VIA_MC97); - pci_realize_and_unref(dev, bus, &error_fatal); -} - static void via_mc97_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 45c596f4fe..8287e65c52 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -262,8 +262,8 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, *i2c_bus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(slot, 4), 0xeee1, NULL); /* Audio support */ - vt82c686b_ac97_init(pci_bus, PCI_DEVFN(slot, 5)); - vt82c686b_mc97_init(pci_bus, PCI_DEVFN(slot, 6)); + pci_create_simple(pci_bus, PCI_DEVFN(slot, 5), TYPE_VIA_AC97); + pci_create_simple(pci_bus, PCI_DEVFN(slot, 6), TYPE_VIA_MC97); } /* Network support */ diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index f23f45dfb1..ff80a926dc 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -3,11 +3,11 @@ #define TYPE_VT82C686B_SUPERIO "vt82c686b-superio" +#define TYPE_VIA_AC97 "via-ac97" +#define TYPE_VIA_MC97 "via-mc97" /* vt82c686.c */ ISABus *vt82c686b_isa_init(PCIBus * bus, int devfn); -void vt82c686b_ac97_init(PCIBus *bus, int devfn); -void vt82c686b_mc97_init(PCIBus *bus, int devfn); I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq); From 657fae258f98000ced6d50a4490a922a207e35f3 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 11/35] vt82c686: Split off via-[am]c97 into separate file in hw/audio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The via-[am]c97 code is supposed to implement the audio part of VIA south bridge chips so it is better placed under hw/audio/. Split it off into a separate file. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/meson.build | 1 + hw/audio/via-ac97.c | 106 +++++++++++++++++++++++++++++++++++++++++++ hw/isa/vt82c686.c | 91 ------------------------------------- 3 files changed, 107 insertions(+), 91 deletions(-) create mode 100644 hw/audio/via-ac97.c diff --git a/hw/audio/meson.build b/hw/audio/meson.build index 549e9a0396..32c42bdebe 100644 --- a/hw/audio/meson.build +++ b/hw/audio/meson.build @@ -11,4 +11,5 @@ softmmu_ss.add(when: 'CONFIG_MILKYMIST', if_true: files('milkymist-ac97.c')) softmmu_ss.add(when: 'CONFIG_PCSPK', if_true: files('pcspk.c')) softmmu_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c')) softmmu_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c')) +softmmu_ss.add(when: 'CONFIG_VT82C686', if_true: files('via-ac97.c')) softmmu_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c')) diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c new file mode 100644 index 0000000000..e617416ff7 --- /dev/null +++ b/hw/audio/via-ac97.c @@ -0,0 +1,106 @@ +/* + * VIA south bridges sound support + * + * This work is licensed under the GNU GPL license version 2 or later. + */ + +/* + * TODO: This is entirely boiler plate just registering empty PCI devices + * with the right ID guests expect, functionality should be added here. + */ + +#include "qemu/osdep.h" +#include "hw/isa/vt82c686.h" +#include "hw/pci/pci.h" + +struct VIAAC97State { + PCIDevice dev; +}; + +struct VIAMC97State { + PCIDevice dev; +}; + +OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97) +OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97) + +static void via_ac97_realize(PCIDevice *dev, Error **errp) +{ + VIAAC97State *s = VIA_AC97(dev); + uint8_t *pci_conf = s->dev.config; + + pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | + PCI_COMMAND_PARITY); + pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST | + PCI_STATUS_DEVSEL_MEDIUM); + pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); +} + +static void via_ac97_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->realize = via_ac97_realize; + k->vendor_id = PCI_VENDOR_ID_VIA; + k->device_id = PCI_DEVICE_ID_VIA_AC97; + k->revision = 0x50; + k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "AC97"; +} + +static const TypeInfo via_ac97_info = { + .name = TYPE_VIA_AC97, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(VIAAC97State), + .class_init = via_ac97_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void via_mc97_realize(PCIDevice *dev, Error **errp) +{ + VIAMC97State *s = VIA_MC97(dev); + uint8_t *pci_conf = s->dev.config; + + pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | + PCI_COMMAND_VGA_PALETTE); + pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); + pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); +} + +static void via_mc97_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->realize = via_mc97_realize; + k->vendor_id = PCI_VENDOR_ID_VIA; + k->device_id = PCI_DEVICE_ID_VIA_MC97; + k->class_id = PCI_CLASS_COMMUNICATION_OTHER; + k->revision = 0x30; + set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "MC97"; +} + +static const TypeInfo via_mc97_info = { + .name = TYPE_VIA_MC97, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(VIAMC97State), + .class_init = via_mc97_class_init, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void via_ac97_register_types(void) +{ + type_register_static(&via_ac97_info); + type_register_static(&via_mc97_info); +} + +type_init(via_ac97_register_types) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 8677a2d212..9567326d8e 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -168,14 +168,6 @@ struct VT686PMState { uint32_t smb_io_base; }; -struct VIAAC97State { - PCIDevice dev; -}; - -struct VIAMC97State { - PCIDevice dev; -}; - #define TYPE_VT82C686B_PM "VT82C686B_PM" OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) @@ -247,87 +239,6 @@ static const VMStateDescription vmstate_acpi = { } }; -/* - * TODO: VIA_AC97 and VIA_MC97 - * just register a PCI device now, functionalities will be implemented later. - */ - -OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97) -OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97) - -static void vt82c686b_ac97_realize(PCIDevice *dev, Error **errp) -{ - VIAAC97State *s = VIA_AC97(dev); - uint8_t *pci_conf = s->dev.config; - - pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | - PCI_COMMAND_PARITY); - pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST | - PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); -} - -static void via_ac97_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = vt82c686b_ac97_realize; - k->vendor_id = PCI_VENDOR_ID_VIA; - k->device_id = PCI_DEVICE_ID_VIA_AC97; - k->revision = 0x50; - k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; - set_bit(DEVICE_CATEGORY_SOUND, dc->categories); - dc->desc = "AC97"; -} - -static const TypeInfo via_ac97_info = { - .name = TYPE_VIA_AC97, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VIAAC97State), - .class_init = via_ac97_class_init, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - -static void vt82c686b_mc97_realize(PCIDevice *dev, Error **errp) -{ - VIAMC97State *s = VIA_MC97(dev); - uint8_t *pci_conf = s->dev.config; - - pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | - PCI_COMMAND_VGA_PALETTE); - pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); -} - -static void via_mc97_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->realize = vt82c686b_mc97_realize; - k->vendor_id = PCI_VENDOR_ID_VIA; - k->device_id = PCI_DEVICE_ID_VIA_MC97; - k->class_id = PCI_CLASS_COMMUNICATION_OTHER; - k->revision = 0x30; - set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); - dc->desc = "MC97"; -} - -static const TypeInfo via_mc97_info = { - .name = TYPE_VIA_MC97, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VIAMC97State), - .class_init = via_mc97_class_init, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, -}; - /* vt82c686 pm init */ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) { @@ -516,8 +427,6 @@ static const TypeInfo via_superio_info = { static void vt82c686b_register_types(void) { - type_register_static(&via_ac97_info); - type_register_static(&via_mc97_info); type_register_static(&via_pm_info); type_register_static(&via_superio_info); type_register_static(&via_info); From a250e1c6e775a2f14819a4412fed77a48253a473 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 12/35] audio/via-ac97: Simplify code and set user_creatable to false MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove some unneded, empty code and set user_creatable to false (besides being not implemented yet, so does nothing anyway) it's also normally part of VIA south bridge chips so no need to confuse users showing them these devices. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/audio/via-ac97.c | 51 +++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index e617416ff7..6d556f74fc 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -13,27 +13,13 @@ #include "hw/isa/vt82c686.h" #include "hw/pci/pci.h" -struct VIAAC97State { - PCIDevice dev; -}; - -struct VIAMC97State { - PCIDevice dev; -}; - -OBJECT_DECLARE_SIMPLE_TYPE(VIAAC97State, VIA_AC97) -OBJECT_DECLARE_SIMPLE_TYPE(VIAMC97State, VIA_MC97) - -static void via_ac97_realize(PCIDevice *dev, Error **errp) +static void via_ac97_realize(PCIDevice *pci_dev, Error **errp) { - VIAAC97State *s = VIA_AC97(dev); - uint8_t *pci_conf = s->dev.config; - - pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | - PCI_COMMAND_PARITY); - pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST | - PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); + pci_set_word(pci_dev->config + PCI_COMMAND, + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY); + pci_set_word(pci_dev->config + PCI_STATUS, + PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM); + pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03); } static void via_ac97_class_init(ObjectClass *klass, void *data) @@ -47,13 +33,15 @@ static void via_ac97_class_init(ObjectClass *klass, void *data) k->revision = 0x50; k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; set_bit(DEVICE_CATEGORY_SOUND, dc->categories); - dc->desc = "AC97"; + dc->desc = "VIA AC97"; + /* Reason: Part of a south bridge chip */ + dc->user_creatable = false; } static const TypeInfo via_ac97_info = { .name = TYPE_VIA_AC97, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VIAAC97State), + .instance_size = sizeof(PCIDevice), .class_init = via_ac97_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, @@ -61,15 +49,12 @@ static const TypeInfo via_ac97_info = { }, }; -static void via_mc97_realize(PCIDevice *dev, Error **errp) +static void via_mc97_realize(PCIDevice *pci_dev, Error **errp) { - VIAMC97State *s = VIA_MC97(dev); - uint8_t *pci_conf = s->dev.config; - - pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_INVALIDATE | - PCI_COMMAND_VGA_PALETTE); - pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_INTERRUPT_PIN, 0x03); + pci_set_word(pci_dev->config + PCI_COMMAND, + PCI_COMMAND_INVALIDATE | PCI_COMMAND_VGA_PALETTE); + pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); + pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03); } static void via_mc97_class_init(ObjectClass *klass, void *data) @@ -83,13 +68,15 @@ static void via_mc97_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_COMMUNICATION_OTHER; k->revision = 0x30; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); - dc->desc = "MC97"; + dc->desc = "VIA MC97"; + /* Reason: Part of a south bridge chip */ + dc->user_creatable = false; } static const TypeInfo via_mc97_info = { .name = TYPE_VIA_MC97, .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(VIAMC97State), + .instance_size = sizeof(PCIDevice), .class_init = via_mc97_class_init, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, From 0bfda9a225b8b50a7e6bebd25ede9df6db8ddd83 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 13/35] vt82c686: Remove legacy vt82c686b_isa_init() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <58d7585f979f154b1f1e69fdc026eed6dbc7996f.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 9 --------- hw/mips/fuloong2e.c | 4 +++- include/hw/isa/vt82c686.h | 3 +-- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 9567326d8e..2912c253dc 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -49,7 +49,6 @@ struct VT82C686BISAState { SuperIOConfig superio_conf; }; -#define TYPE_VT82C686B_ISA "vt82c686b-isa" OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, @@ -367,14 +366,6 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) &vt82c->superio); } -ISABus *vt82c686b_isa_init(PCIBus *bus, int devfn) -{ - PCIDevice *d; - - d = pci_create_simple_multifunction(bus, devfn, true, TYPE_VT82C686B_ISA); - return ISA_BUS(qdev_get_child_bus(DEVICE(d), "isa.0")); -} - static void via_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 8287e65c52..435f0e5be5 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -240,7 +240,9 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, ISABus *isa_bus; PCIDevice *dev; - isa_bus = vt82c686b_isa_init(pci_bus, PCI_DEVFN(slot, 0)); + dev = pci_create_simple_multifunction(pci_bus, PCI_DEVFN(slot, 0), true, + TYPE_VT82C686B_ISA); + isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(dev), "isa.0")); assert(isa_bus); *p_isa_bus = isa_bus; /* Interrupt controller */ diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index ff80a926dc..8d2d276fe1 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -1,13 +1,12 @@ #ifndef HW_VT82C686_H #define HW_VT82C686_H - +#define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_SUPERIO "vt82c686b-superio" #define TYPE_VIA_AC97 "via-ac97" #define TYPE_VIA_MC97 "via-mc97" /* vt82c686.c */ -ISABus *vt82c686b_isa_init(PCIBus * bus, int devfn); I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, qemu_irq sci_irq); From dc66439542c1772f2290c0908814580db9377f23 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 14/35] vt82c686: Remove legacy vt82c686b_pm_init() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove legacy vt82c686b_pm_init() function and also rename VT82C686B_PM type name to match other device names. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 18 ------------------ hw/mips/fuloong2e.c | 5 ++++- include/hw/isa/vt82c686.h | 5 +---- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 2912c253dc..cd87ec0103 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -12,7 +12,6 @@ #include "qemu/osdep.h" #include "hw/isa/vt82c686.h" -#include "hw/i2c/i2c.h" #include "hw/pci/pci.h" #include "hw/qdev-properties.h" #include "hw/isa/isa.h" @@ -167,7 +166,6 @@ struct VT686PMState { uint32_t smb_io_base; }; -#define TYPE_VT82C686B_PM "VT82C686B_PM" OBJECT_DECLARE_SIMPLE_TYPE(VT686PMState, VT82C686B_PM) static void pm_update_sci(VT686PMState *s) @@ -271,22 +269,6 @@ static void vt82c686b_pm_realize(PCIDevice *dev, Error **errp) acpi_pm1_cnt_init(&s->ar, &s->io, false, false, 2); } -I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq) -{ - PCIDevice *dev; - VT686PMState *s; - - dev = pci_new(devfn, TYPE_VT82C686B_PM); - qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base); - - s = VT82C686B_PM(dev); - - pci_realize_and_unref(dev, bus, &error_fatal); - - return s->smb.smbus; -} - static Property via_pm_properties[] = { DEFINE_PROP_UINT32("smb_io_base", VT686PMState, smb_io_base, 0), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 435f0e5be5..e5d0866906 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -261,7 +261,10 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, pci_create_simple(pci_bus, PCI_DEVFN(slot, 2), "vt82c686b-usb-uhci"); pci_create_simple(pci_bus, PCI_DEVFN(slot, 3), "vt82c686b-usb-uhci"); - *i2c_bus = vt82c686b_pm_init(pci_bus, PCI_DEVFN(slot, 4), 0xeee1, NULL); + dev = pci_new(PCI_DEVFN(slot, 4), TYPE_VT82C686B_PM); + qdev_prop_set_uint32(DEVICE(dev), "smb_io_base", 0xeee1); + pci_realize_and_unref(dev, pci_bus, &error_fatal); + *i2c_bus = I2C_BUS(qdev_get_child_bus(DEVICE(dev), "i2c")); /* Audio support */ pci_create_simple(pci_bus, PCI_DEVFN(slot, 5), TYPE_VIA_AC97); diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index 8d2d276fe1..5b0a1ffe72 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -3,11 +3,8 @@ #define TYPE_VT82C686B_ISA "vt82c686b-isa" #define TYPE_VT82C686B_SUPERIO "vt82c686b-superio" +#define TYPE_VT82C686B_PM "vt82c686b-pm" #define TYPE_VIA_AC97 "via-ac97" #define TYPE_VIA_MC97 "via-mc97" -/* vt82c686.c */ -I2CBus *vt82c686b_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq); - #endif From ff413a1f7f65bb7fbd9489de29b04253f2fdaf1a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 15/35] vt82c686: Convert debug printf to trace points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop DPRINTF and use trace functions instead. Two debug messages about unimplemented registers could be converted to qemu_log_mask() but in reality all registers are currently unimplemented (we just store and return values of writable regs but do nothing with them). As we already trace register access there's no need for additional debug messages so these are just removed and a comment is added as a reminder. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <785854022a37035f66d89e70cb6ca1bc0e0d0163.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/trace-events | 6 ++++++ hw/isa/vt82c686.c | 51 +++++++++++++-------------------------------- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/hw/isa/trace-events b/hw/isa/trace-events index 3544c6213c..d267d3e652 100644 --- a/hw/isa/trace-events +++ b/hw/isa/trace-events @@ -13,3 +13,9 @@ pc87312_io_write(uint32_t addr, uint32_t val) "write addr=0x%x val=0x%x" # apm.c apm_io_read(uint8_t addr, uint8_t val) "read addr=0x%x val=0x%02x" apm_io_write(uint8_t addr, uint8_t val) "write addr=0x%x val=0x%02x" + +# vt82c686.c +via_isa_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" +via_pm_write(uint32_t addr, uint32_t val, int len) "addr 0x%x val 0x%x len 0x%x" +via_superio_read(uint8_t addr, uint8_t val) "addr 0x%x val 0x%x" +via_superio_write(uint8_t addr, uint32_t val) "addr 0x%x val 0x%x" diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index cd87ec0103..d7ce15bf9f 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -27,14 +27,7 @@ #include "qemu/timer.h" #include "exec/address-spaces.h" #include "qom/object.h" - -/* #define DEBUG_VT82C686B */ - -#ifdef DEBUG_VT82C686B -#define DPRINTF(fmt, ...) fprintf(stderr, "%s: " fmt, __func__, ##__VA_ARGS__) -#else -#define DPRINTF(fmt, ...) -#endif +#include "trace.h" typedef struct SuperIOConfig { uint8_t config[0x100]; @@ -55,12 +48,12 @@ static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, { SuperIOConfig *superio_conf = opaque; - DPRINTF("superio_ioport_writeb address 0x%x val 0x%x\n", addr, data); - if (addr == 0x3f0) { + if (addr == 0x3f0) { /* config index register */ superio_conf->index = data & 0xff; } else { bool can_write = true; - /* 0x3f1 */ + /* 0x3f1, config data register */ + trace_via_superio_write(superio_conf->index, data & 0xff); switch (superio_conf->index) { case 0x00 ... 0xdf: case 0xe4: @@ -73,18 +66,7 @@ static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, case 0xfd ... 0xff: can_write = false; break; - case 0xe7: - if ((data & 0xff) != 0xfe) { - DPRINTF("change uart 1 base. unsupported yet\n"); - can_write = false; - } - break; - case 0xe8: - if ((data & 0xff) != 0xbe) { - DPRINTF("change uart 2 base. unsupported yet\n"); - can_write = false; - } - break; + /* case 0xe6 ... 0xe8: Should set base port of parallel and serial */ default: break; @@ -98,9 +80,10 @@ static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, static uint64_t superio_ioport_readb(void *opaque, hwaddr addr, unsigned size) { SuperIOConfig *superio_conf = opaque; + uint8_t val = superio_conf->config[superio_conf->index]; - DPRINTF("superio_ioport_readb address 0x%x\n", addr); - return superio_conf->config[superio_conf->index]; + trace_via_superio_read(superio_conf->index, val); + return val; } static const MemoryRegionOps superio_ops = { @@ -141,16 +124,14 @@ static void vt82c686b_isa_reset(DeviceState *dev) } /* write config pci function0 registers. PCI-ISA bridge */ -static void vt82c686b_write_config(PCIDevice *d, uint32_t address, +static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { VT82C686BISAState *vt686 = VT82C686B_ISA(d); - DPRINTF("vt82c686b_write_config address 0x%x val 0x%x len 0x%x\n", - address, val, len); - - pci_default_write_config(d, address, val, len); - if (address == 0x85) { /* enable or disable super IO configure */ + trace_via_isa_write(addr, val, len); + pci_default_write_config(d, addr, val, len); + if (addr == 0x85) { /* enable or disable super IO configure */ memory_region_set_enabled(&vt686->superio, val & 0x2); } } @@ -203,12 +184,10 @@ static void pm_io_space_update(VT686PMState *s) memory_region_transaction_commit(); } -static void pm_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len) +static void pm_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { - DPRINTF("pm_write_config address 0x%x val 0x%x len 0x%x\n", - address, val, len); - pci_default_write_config(d, address, val, len); + trace_via_pm_write(addr, val, len); + pci_default_write_config(d, addr, val, len); } static int vmstate_acpi_post_load(void *opaque, int version_id) From 9b0fbae2cbf8ff47c731a476d4c4ec824394fb6b Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 16/35] vt82c686: Remove unneeded includes and defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are not used or not needed. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <35cefcc3518a3395a796bb6ad6fbc308adc65266.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index d7ce15bf9f..02d6759c00 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -16,9 +16,7 @@ #include "hw/qdev-properties.h" #include "hw/isa/isa.h" #include "hw/isa/superio.h" -#include "hw/sysbus.h" #include "migration/vmstate.h" -#include "hw/mips/mips.h" #include "hw/isa/apm.h" #include "hw/acpi/acpi.h" #include "hw/i2c/pm_smbus.h" @@ -26,7 +24,6 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "exec/address-spaces.h" -#include "qom/object.h" #include "trace.h" typedef struct SuperIOConfig { @@ -136,8 +133,6 @@ static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, } } -#define ACPI_DBG_IO_ADDR 0xb044 - struct VT686PMState { PCIDevice dev; MemoryRegion io; From 007b3103a393bb6123354e7d81650a761b62a66f Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 17/35] vt82c686: Use shorter name for local variable holding object state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename local variable holding object state for readability and consistency. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <69655b23df2ecebbf0aff29726f4b4746f5b74de.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 02d6759c00..2633cfe7dc 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -95,8 +95,8 @@ static const MemoryRegionOps superio_ops = { static void vt82c686b_isa_reset(DeviceState *dev) { - VT82C686BISAState *vt82c = VT82C686B_ISA(dev); - uint8_t *pci_conf = vt82c->dev.config; + VT82C686BISAState *s = VT82C686B_ISA(dev); + uint8_t *pci_conf = s->dev.config; pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | @@ -112,24 +112,24 @@ static void vt82c686b_isa_reset(DeviceState *dev) pci_conf[0x5f] = 0x04; pci_conf[0x77] = 0x10; /* GPIO Control 1/2/3/4 */ - vt82c->superio_conf.config[0xe0] = 0x3c; - vt82c->superio_conf.config[0xe2] = 0x03; - vt82c->superio_conf.config[0xe3] = 0xfc; - vt82c->superio_conf.config[0xe6] = 0xde; - vt82c->superio_conf.config[0xe7] = 0xfe; - vt82c->superio_conf.config[0xe8] = 0xbe; + s->superio_conf.config[0xe0] = 0x3c; + s->superio_conf.config[0xe2] = 0x03; + s->superio_conf.config[0xe3] = 0xfc; + s->superio_conf.config[0xe6] = 0xde; + s->superio_conf.config[0xe7] = 0xfe; + s->superio_conf.config[0xe8] = 0xbe; } /* write config pci function0 registers. PCI-ISA bridge */ static void vt82c686b_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len) { - VT82C686BISAState *vt686 = VT82C686B_ISA(d); + VT82C686BISAState *s = VT82C686B_ISA(d); trace_via_isa_write(addr, val, len); pci_default_write_config(d, addr, val, len); if (addr == 0x85) { /* enable or disable super IO configure */ - memory_region_set_enabled(&vt686->superio, val & 0x2); + memory_region_set_enabled(&s->superio, val & 0x2); } } @@ -289,7 +289,7 @@ static const VMStateDescription vmstate_via = { /* init the PCI-to-ISA bridge */ static void vt82c686b_realize(PCIDevice *d, Error **errp) { - VT82C686BISAState *vt82c = VT82C686B_ISA(d); + VT82C686BISAState *s = VT82C686B_ISA(d); uint8_t *pci_conf; ISABus *isa_bus; uint8_t *wmask; @@ -311,15 +311,15 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) } } - memory_region_init_io(&vt82c->superio, OBJECT(d), &superio_ops, - &vt82c->superio_conf, "superio", 2); - memory_region_set_enabled(&vt82c->superio, false); + memory_region_init_io(&s->superio, OBJECT(d), &superio_ops, + &s->superio_conf, "superio", 2); + memory_region_set_enabled(&s->superio, false); /* * The floppy also uses 0x3f0 and 0x3f1. * But we do not emulate a floppy, so just set it here. */ memory_region_add_subregion(isa_bus->address_space_io, 0x3f0, - &vt82c->superio); + &s->superio); } static void via_class_init(ObjectClass *klass, void *data) From 7886a674f13320c8e1a0744f3794e8caeeff874a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Sat, 2 Jan 2021 11:43:35 +0100 Subject: [PATCH 18/35] vt82c686: Rename superio config related parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use less confusing naming for superio config register handling related parts that makes it clearer what belongs to this part. Signed-off-by: BALATON Zoltan Reviewed-by: Philippe Mathieu-Daudé Message-Id: <4d30a2b4b771b2ad651509885daae79d7c4fe7a8.1609584216.git.balaton@eik.bme.hu> Signed-off-by: Philippe Mathieu-Daudé --- hw/isa/vt82c686.c | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 2633cfe7dc..a6f5a0843d 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -27,7 +27,7 @@ #include "trace.h" typedef struct SuperIOConfig { - uint8_t config[0x100]; + uint8_t regs[0x100]; uint8_t index; uint8_t data; } SuperIOConfig; @@ -35,23 +35,23 @@ typedef struct SuperIOConfig { struct VT82C686BISAState { PCIDevice dev; MemoryRegion superio; - SuperIOConfig superio_conf; + SuperIOConfig superio_cfg; }; OBJECT_DECLARE_SIMPLE_TYPE(VT82C686BISAState, VT82C686B_ISA) -static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, - unsigned size) +static void superio_cfg_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) { - SuperIOConfig *superio_conf = opaque; + SuperIOConfig *sc = opaque; if (addr == 0x3f0) { /* config index register */ - superio_conf->index = data & 0xff; + sc->index = data & 0xff; } else { bool can_write = true; /* 0x3f1, config data register */ - trace_via_superio_write(superio_conf->index, data & 0xff); - switch (superio_conf->index) { + trace_via_superio_write(sc->index, data & 0xff); + switch (sc->index) { case 0x00 ... 0xdf: case 0xe4: case 0xe5: @@ -69,23 +69,23 @@ static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, } if (can_write) { - superio_conf->config[superio_conf->index] = data & 0xff; + sc->regs[sc->index] = data & 0xff; } } } -static uint64_t superio_ioport_readb(void *opaque, hwaddr addr, unsigned size) +static uint64_t superio_cfg_read(void *opaque, hwaddr addr, unsigned size) { - SuperIOConfig *superio_conf = opaque; - uint8_t val = superio_conf->config[superio_conf->index]; + SuperIOConfig *sc = opaque; + uint8_t val = sc->regs[sc->index]; - trace_via_superio_read(superio_conf->index, val); + trace_via_superio_read(sc->index, val); return val; } -static const MemoryRegionOps superio_ops = { - .read = superio_ioport_readb, - .write = superio_ioport_writeb, +static const MemoryRegionOps superio_cfg_ops = { + .read = superio_cfg_read, + .write = superio_cfg_write, .endianness = DEVICE_NATIVE_ENDIAN, .impl = { .min_access_size = 1, @@ -112,12 +112,12 @@ static void vt82c686b_isa_reset(DeviceState *dev) pci_conf[0x5f] = 0x04; pci_conf[0x77] = 0x10; /* GPIO Control 1/2/3/4 */ - s->superio_conf.config[0xe0] = 0x3c; - s->superio_conf.config[0xe2] = 0x03; - s->superio_conf.config[0xe3] = 0xfc; - s->superio_conf.config[0xe6] = 0xde; - s->superio_conf.config[0xe7] = 0xfe; - s->superio_conf.config[0xe8] = 0xbe; + s->superio_cfg.regs[0xe0] = 0x3c; /* Device ID */ + s->superio_cfg.regs[0xe2] = 0x03; /* Function select */ + s->superio_cfg.regs[0xe3] = 0xfc; /* Floppy ctrl base addr */ + s->superio_cfg.regs[0xe6] = 0xde; /* Parallel port base addr */ + s->superio_cfg.regs[0xe7] = 0xfe; /* Serial port 1 base addr */ + s->superio_cfg.regs[0xe8] = 0xbe; /* Serial port 2 base addr */ } /* write config pci function0 registers. PCI-ISA bridge */ @@ -311,8 +311,8 @@ static void vt82c686b_realize(PCIDevice *d, Error **errp) } } - memory_region_init_io(&s->superio, OBJECT(d), &superio_ops, - &s->superio_conf, "superio", 2); + memory_region_init_io(&s->superio, OBJECT(d), &superio_cfg_ops, + &s->superio_cfg, "superio", 2); memory_region_set_enabled(&s->superio, false); /* * The floppy also uses 0x3f0 and 0x3f1. From 554d523785ef8681905ec13ad28a025ec0af40fe Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:09:26 +0000 Subject: [PATCH 19/35] clock: Introduce clock_ticks_to_ns() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clock_get_ns() API claims to return the period of a clock in nanoseconds. Unfortunately since it returns an integer and a clock's period is represented in units of 2^-32 nanoseconds, the result is often an approximation, and calculating a clock expiry deadline by multiplying clock_get_ns() by a number-of-ticks is unacceptably inaccurate. Introduce a new API clock_ticks_to_ns() which returns the number of nanoseconds it takes the clock to make a given number of ticks. This function can do the complete calculation internally and will thus give a more accurate result. Signed-off-by: Peter Maydell Tested-by: Philippe Mathieu-Daudé Reviewed-by: Luc Michel Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201215150929.30311-2-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/clocks.rst | 29 +++++++++++++++++++++++++++++ include/hw/clock.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst index e5da28e211..c2e70e64db 100644 --- a/docs/devel/clocks.rst +++ b/docs/devel/clocks.rst @@ -258,6 +258,35 @@ Here is an example: clock_get_ns(dev->my_clk_input)); } +Calculating expiry deadlines +---------------------------- + +A commonly required operation for a clock is to calculate how long +it will take for the clock to tick N times; this can then be used +to set a timer expiry deadline. Use the function ``clock_ticks_to_ns()``, +which takes an unsigned 64-bit count of ticks and returns the length +of time in nanoseconds required for the clock to tick that many times. + +It is important not to try to calculate expiry deadlines using a +shortcut like multiplying a "period of clock in nanoseconds" value +by the tick count, because clocks can have periods which are not a +whole number of nanoseconds, and the accumulated error in the +multiplication can be significant. + +For a clock with a very long period and a large number of ticks, +the result of this function could in theory be too large to fit in +a 64-bit value. To avoid overflow in this case, ``clock_ticks_to_ns()`` +saturates the result to INT64_MAX (because this is the largest valid +input to the QEMUTimer APIs). Since INT64_MAX nanoseconds is almost +300 years, anything with an expiry later than that is in the "will +never happen" category. Callers of ``clock_ticks_to_ns()`` should +therefore generally not special-case the possibility of a saturated +result but just allow the timer to be set to that far-future value. +(If you are performing further calculations on the returned value +rather than simply passing it to a QEMUTimer function like +``timer_mod_ns()`` then you should be careful to avoid overflow +in those calculations, of course.) + Changing a clock period ----------------------- diff --git a/include/hw/clock.h b/include/hw/clock.h index 81bcf3e505..b5fff6ded8 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -16,6 +16,8 @@ #include "qom/object.h" #include "qemu/queue.h" +#include "qemu/host-utils.h" +#include "qemu/bitops.h" #define TYPE_CLOCK "clock" OBJECT_DECLARE_SIMPLE_TYPE(Clock, CLOCK) @@ -218,6 +220,45 @@ static inline unsigned clock_get_ns(Clock *clk) return CLOCK_PERIOD_TO_NS(clock_get(clk)); } +/** + * clock_ticks_to_ns: + * @clk: the clock to query + * @ticks: number of ticks + * + * Returns the length of time in nanoseconds for this clock + * to tick @ticks times. Because a clock can have a period + * which is not a whole number of nanoseconds, it is important + * to use this function when calculating things like timer + * expiry deadlines, rather than attempting to obtain a "period + * in nanoseconds" value and then multiplying that by a number + * of ticks. + * + * The result could in theory be too large to fit in a 64-bit + * value if the number of ticks and the clock period are both + * large; to avoid overflow the result will be saturated to INT64_MAX + * (because this is the largest valid input to the QEMUTimer APIs). + * Since INT64_MAX nanoseconds is almost 300 years, anything with + * an expiry later than that is in the "will never happen" category + * and callers can reasonably not special-case the saturated result. + */ +static inline uint64_t clock_ticks_to_ns(const Clock *clk, uint64_t ticks) +{ + uint64_t ns_low, ns_high; + + /* + * clk->period is the period in units of 2^-32 ns, so + * (clk->period * ticks) is the required length of time in those + * units, and we can convert to nanoseconds by multiplying by + * 2^32, which is the same as shifting the 128-bit multiplication + * result right by 32. + */ + mulu64(&ns_low, &ns_high, clk->period, ticks); + if (ns_high & MAKE_64BIT_MASK(31, 33)) { + return INT64_MAX; + } + return ns_low >> 32 | ns_high << 32; +} + /** * clock_is_enabled: * @clk: a clock From 0ac1fb256742f665449c3dd02dd0ed7a5112cea1 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:09:27 +0000 Subject: [PATCH 20/35] target/mips: Don't use clock_get_ns() in clock period calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the MIPS code uses the old clock_get_ns() API to calculate a time length in nanoseconds: cpu->cp0_count_rate * clock_get_ns(MIPS_CPU(cpu)->clock) This relies on the clock having a period which is an exact number of nanoseconds. Switch to the new clock_ticks_to_ns() function, which does the multiplication internally at a higher precision. Signed-off-by: Peter Maydell Tested-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201215150929.30311-3-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- target/mips/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/mips/cpu.c b/target/mips/cpu.c index b2cd69ff7f..2283214c87 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -380,8 +380,8 @@ static void mips_cp0_period_set(MIPSCPU *cpu) { CPUMIPSState *env = &cpu->env; - env->cp0_count_ns = cpu->cp0_count_rate - * clock_get_ns(MIPS_CPU(cpu)->clock); + env->cp0_count_ns = clock_ticks_to_ns(MIPS_CPU(cpu)->clock, + cpu->cp0_count_rate); assert(env->cp0_count_ns); } From de6a65f11d7e5a2a93f2b75c0d434ab6ed7f68c8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:09:28 +0000 Subject: [PATCH 21/35] clock: Remove clock_get_ns() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the now-unused clock_get_ns() API and the CLOCK_PERIOD_TO_NS() macro that only it was using. Signed-off-by: Peter Maydell Tested-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201215150929.30311-4-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/clocks.rst | 17 +++++++++++++---- include/hw/clock.h | 6 ------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst index c2e70e64db..2d317ff32f 100644 --- a/docs/devel/clocks.rst +++ b/docs/devel/clocks.rst @@ -238,8 +238,17 @@ object during device instance init. For example: Fetching clock frequency/period ------------------------------- -To get the current state of a clock, use the functions ``clock_get()``, -``clock_get_ns()`` or ``clock_get_hz()``. +To get the current state of a clock, use the functions ``clock_get()`` +or ``clock_get_hz()``. + +``clock_get()`` returns the period of the clock in its fully precise +internal representation, as an unsigned 64-bit integer in units of +2^-32 nanoseconds. (For many purposes ``clock_ticks_to_ns()`` will +be more convenient; see the section below on expiry deadlines.) + +``clock_get_hz()`` returns the frequency of the clock, rounded to the +next lowest integer. This implies some inaccuracy due to the rounding, +so be cautious about using it in calculations. It is also possible to register a callback on clock frequency changes. Here is an example: @@ -254,8 +263,8 @@ Here is an example: */ /* do something with the new period */ - fprintf(stdout, "device new period is %" PRIu64 "ns\n", - clock_get_ns(dev->my_clk_input)); + fprintf(stdout, "device new period is %" PRIu64 "* 2^-32 ns\n", + clock_get(dev->my_clk_input)); } Calculating expiry deadlines diff --git a/include/hw/clock.h b/include/hw/clock.h index b5fff6ded8..852c636961 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -40,7 +40,6 @@ typedef void ClockCallback(void *opaque); * macro helpers to convert to hertz / nanosecond */ #define CLOCK_PERIOD_FROM_NS(ns) ((ns) * (CLOCK_PERIOD_1SEC / 1000000000llu)) -#define CLOCK_PERIOD_TO_NS(per) ((per) / (CLOCK_PERIOD_1SEC / 1000000000llu)) #define CLOCK_PERIOD_FROM_HZ(hz) (((hz) != 0) ? CLOCK_PERIOD_1SEC / (hz) : 0u) #define CLOCK_PERIOD_TO_HZ(per) (((per) != 0) ? CLOCK_PERIOD_1SEC / (per) : 0u) @@ -215,11 +214,6 @@ static inline unsigned clock_get_hz(Clock *clk) return CLOCK_PERIOD_TO_HZ(clock_get(clk)); } -static inline unsigned clock_get_ns(Clock *clk) -{ - return CLOCK_PERIOD_TO_NS(clock_get(clk)); -} - /** * clock_ticks_to_ns: * @clk: the clock to query From b7cd9c1e840d511319f326ee8cab772b3ac50a3b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Dec 2020 15:09:29 +0000 Subject: [PATCH 22/35] clock: Define and use new clock_display_freq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's common to want to print a human-readable indication of a clock's frequency. Provide a utility function in the clock API to return a string which is a displayable representation of the frequency, and use it in qdev-monitor.c. Before: (qemu) info qtree [...] dev: xilinx,zynq_slcr, id "" clock-in "ps_clk" freq_hz=3.333333e+07 mmio 00000000f8000000/0000000000001000 After: dev: xilinx,zynq_slcr, id "" clock-in "ps_clk" freq_hz=33.3 MHz mmio 00000000f8000000/0000000000001000 Signed-off-by: Peter Maydell Tested-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Luc Michel Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201215150929.30311-5-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/clocks.rst | 5 +++++ hw/core/clock.c | 6 ++++++ include/hw/clock.h | 12 ++++++++++++ softmmu/qdev-monitor.c | 6 +++--- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst index 2d317ff32f..2548d84232 100644 --- a/docs/devel/clocks.rst +++ b/docs/devel/clocks.rst @@ -267,6 +267,11 @@ Here is an example: clock_get(dev->my_clk_input)); } +If you are only interested in the frequency for displaying it to +humans (for instance in debugging), use ``clock_display_freq()``, +which returns a prettified string-representation, e.g. "33.3 MHz". +The caller must free the string with g_free() after use. + Calculating expiry deadlines ---------------------------- diff --git a/hw/core/clock.c b/hw/core/clock.c index 8c6af223e7..76b5f468b6 100644 --- a/hw/core/clock.c +++ b/hw/core/clock.c @@ -12,6 +12,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "hw/clock.h" #include "trace.h" @@ -111,6 +112,11 @@ static void clock_disconnect(Clock *clk) QLIST_REMOVE(clk, sibling); } +char *clock_display_freq(Clock *clk) +{ + return freq_to_str(clock_get_hz(clk)); +} + static void clock_initfn(Object *obj) { Clock *clk = CLOCK(obj); diff --git a/include/hw/clock.h b/include/hw/clock.h index 852c636961..6382f34656 100644 --- a/include/hw/clock.h +++ b/include/hw/clock.h @@ -264,4 +264,16 @@ static inline bool clock_is_enabled(const Clock *clk) return clock_get(clk) != 0; } +/** + * clock_display_freq: return human-readable representation of clock frequency + * @clk: clock + * + * Return a string which has a human-readable representation of the + * clock's frequency, e.g. "33.3 MHz". This is intended for debug + * and display purposes. + * + * The caller is responsible for freeing the string with g_free(). + */ +char *clock_display_freq(Clock *clk); + #endif /* QEMU_HW_CLOCK_H */ diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 2c57e36c9a..8dc656becc 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -736,11 +736,11 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) } } QLIST_FOREACH(ncl, &dev->clocks, node) { - qdev_printf("clock-%s%s \"%s\" freq_hz=%e\n", + g_autofree char *freq_str = clock_display_freq(ncl->clock); + qdev_printf("clock-%s%s \"%s\" freq_hz=%s\n", ncl->output ? "out" : "in", ncl->alias ? " (alias)" : "", - ncl->name, - CLOCK_PERIOD_TO_HZ(1.0 * clock_get(ncl->clock))); + ncl->name, freq_str); } class = object_get_class(OBJECT(dev)); do { From dea96332327f2651f726244cc5bb41c4f9350f8b Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Mon, 21 Dec 2020 19:05:34 +0800 Subject: [PATCH 23/35] hw/intc: Rework Loongson LIOINTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc: 1, Move macro definitions to loongson_liointc.h; 2, Remove magic values and use macros instead; 3, Replace dead D() code by trace events. Suggested-by: Philippe Mathieu-Daudé Signed-off-by: Huacai Chen Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201221110538.3186646-2-chenhuacai@kernel.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/intc/loongson_liointc.c | 36 +++++++++++++----------------- include/hw/intc/loongson_liointc.h | 22 ++++++++++++++++++ 2 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 include/hw/intc/loongson_liointc.h diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c index fbbfb57ee9..f823d484e0 100644 --- a/hw/intc/loongson_liointc.c +++ b/hw/intc/loongson_liointc.c @@ -1,6 +1,7 @@ /* * QEMU Loongson Local I/O interrupt controler. * + * Copyright (c) 2020 Huacai Chen * Copyright (c) 2020 Jiaxun Yang * * This program is free software: you can redistribute it and/or modify @@ -19,13 +20,11 @@ */ #include "qemu/osdep.h" -#include "hw/sysbus.h" #include "qemu/module.h" +#include "qemu/log.h" #include "hw/irq.h" #include "hw/qdev-properties.h" -#include "qom/object.h" - -#define D(x) +#include "hw/intc/loongson_liointc.h" #define NUM_IRQS 32 @@ -40,13 +39,10 @@ #define R_IEN 0x24 #define R_IEN_SET 0x28 #define R_IEN_CLR 0x2c -#define R_PERCORE_ISR(x) (0x40 + 0x8 * x) +#define R_ISR_SIZE 0x8 +#define R_START 0x40 #define R_END 0x64 -#define TYPE_LOONGSON_LIOINTC "loongson.liointc" -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC, - TYPE_LOONGSON_LIOINTC) - struct loongson_liointc { SysBusDevice parent_obj; @@ -123,14 +119,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size) goto out; } - /* Rest is 4 byte */ + /* Rest are 4 bytes */ if (size != 4 || (addr % 4)) { goto out; } - if (addr >= R_PERCORE_ISR(0) && - addr < R_PERCORE_ISR(NUM_CORES)) { - int core = (addr - R_PERCORE_ISR(0)) / 8; + if (addr >= R_START && addr < R_END) { + int core = (addr - R_START) / R_ISR_SIZE; r = p->per_core_isr[core]; goto out; } @@ -147,7 +142,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size) } out: - D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r)); + qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%"HWADDR_PRIx", val=%x\n", + __func__, size, addr, r); return r; } @@ -158,7 +154,8 @@ liointc_write(void *opaque, hwaddr addr, struct loongson_liointc *p = opaque; uint32_t value = val64; - D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value)); + qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%"HWADDR_PRIx", val=%x\n", + __func__, size, addr, value); /* Mapper is 1 byte */ if (size == 1 && addr < R_MAPPER_END) { @@ -166,14 +163,13 @@ liointc_write(void *opaque, hwaddr addr, goto out; } - /* Rest is 4 byte */ + /* Rest are 4 bytes */ if (size != 4 || (addr % 4)) { goto out; } - if (addr >= R_PERCORE_ISR(0) && - addr < R_PERCORE_ISR(NUM_CORES)) { - int core = (addr - R_PERCORE_ISR(0)) / 8; + if (addr >= R_START && addr < R_END) { + int core = (addr - R_START) / R_ISR_SIZE; p->per_core_isr[core] = value; goto out; } @@ -224,7 +220,7 @@ static void loongson_liointc_init(Object *obj) } memory_region_init_io(&p->mmio, obj, &pic_ops, p, - "loongson.liointc", R_END); + TYPE_LOONGSON_LIOINTC, R_END); sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio); } diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h new file mode 100644 index 0000000000..848e65eb35 --- /dev/null +++ b/include/hw/intc/loongson_liointc.h @@ -0,0 +1,22 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2020 Huacai Chen + * Copyright (c) 2020 Jiaxun Yang + * + */ + +#ifndef LOONGSON_LIOINTC_H +#define LOONGSON_LIOINTC_H + +#include "qemu/units.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_LOONGSON_LIOINTC "loongson.liointc" +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC, + TYPE_LOONGSON_LIOINTC) + +#endif /* LOONGSON_LIOINTC_H */ From 313d1e910ac0eb12bbfe83f158cab60f600319f1 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Tue, 22 Sep 2020 10:49:25 +0800 Subject: [PATCH 24/35] hw/mips: Implement fw_cfg_arch_key_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement fw_cfg_arch_key_name(), which returns the name of a mips-specific key. Co-developed-by: Jiaxun Yang Signed-off-by: Huacai Chen Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <1600742967-12933-7-git-send-email-chenhc@lemote.com> [PMD: Add FW_CFG_MIPS Kconfig selector] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/Kconfig | 3 +++ hw/mips/fw_cfg.c | 35 +++++++++++++++++++++++++++++++++++ hw/mips/fw_cfg.h | 19 +++++++++++++++++++ hw/mips/meson.build | 1 + 4 files changed, 58 insertions(+) create mode 100644 hw/mips/fw_cfg.c create mode 100644 hw/mips/fw_cfg.h diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 8be70122f4..64ef42dd3f 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -38,3 +38,6 @@ config MIPS_CPS config MIPS_BOSTON bool + +config FW_CFG_MIPS + bool diff --git a/hw/mips/fw_cfg.c b/hw/mips/fw_cfg.c new file mode 100644 index 0000000000..67c4a74f4b --- /dev/null +++ b/hw/mips/fw_cfg.c @@ -0,0 +1,35 @@ +/* + * QEMU fw_cfg helpers (MIPS specific) + * + * Copyright (c) 2020 Lemote, Inc. + * + * Author: + * Huacai Chen (chenhc@lemote.com) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "hw/mips/fw_cfg.h" +#include "hw/nvram/fw_cfg.h" + +const char *fw_cfg_arch_key_name(uint16_t key) +{ + static const struct { + uint16_t key; + const char *name; + } fw_cfg_arch_wellknown_keys[] = { + {FW_CFG_MACHINE_VERSION, "machine_version"}, + {FW_CFG_CPU_FREQ, "cpu_frequency"}, + }; + + for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) { + if (fw_cfg_arch_wellknown_keys[i].key == key) { + return fw_cfg_arch_wellknown_keys[i].name; + } + } + return NULL; +} diff --git a/hw/mips/fw_cfg.h b/hw/mips/fw_cfg.h new file mode 100644 index 0000000000..e317d5b9a3 --- /dev/null +++ b/hw/mips/fw_cfg.h @@ -0,0 +1,19 @@ +/* + * QEMU fw_cfg helpers (MIPS specific) + * + * Copyright (c) 2020 Huacai Chen + * + * SPDX-License-Identifier: MIT + */ + +#ifndef HW_MIPS_FW_CFG_H +#define HW_MIPS_FW_CFG_H + +#include "hw/boards.h" +#include "hw/nvram/fw_cfg.h" + +/* Data for BIOS to identify machine */ +#define FW_CFG_MACHINE_VERSION (FW_CFG_ARCH_LOCAL + 0) +#define FW_CFG_CPU_FREQ (FW_CFG_ARCH_LOCAL + 1) + +#endif diff --git a/hw/mips/meson.build b/hw/mips/meson.build index 77b4d8f365..ca5e4d0f94 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -1,5 +1,6 @@ mips_ss = ss.source_set() mips_ss.add(files('mips_int.c')) +mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c')) From d2245e2de0201d7dfaff66c6851934af2d23bbfc Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Fri, 16 Oct 2020 14:51:58 +0800 Subject: [PATCH 25/35] hw/mips: Add Loongson-3 boot parameter helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers first. Co-developed-by: Jiaxun Yang Signed-off-by: Huacai Chen Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201221110538.3186646-4-chenhuacai@kernel.org> [PMD: Fixed typo] Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 2 + hw/mips/loongson3_bootp.c | 151 ++++++++++++++++++++++++ hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++ hw/mips/meson.build | 1 + 4 files changed, 395 insertions(+) create mode 100644 hw/mips/loongson3_bootp.c create mode 100644 hw/mips/loongson3_bootp.h diff --git a/MAINTAINERS b/MAINTAINERS index 42fedf91e7..29c5e3b13c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1159,6 +1159,8 @@ M: Huacai Chen R: Jiaxun Yang S: Maintained F: hw/intc/loongson_liointc.c +F: hw/mips/loongson3_bootp.c +F: hw/mips/loongson3_bootp.h Boston M: Paul Burton diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c new file mode 100644 index 0000000000..f99af22932 --- /dev/null +++ b/hw/mips/loongson3_bootp.c @@ -0,0 +1,151 @@ +/* + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers + * + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com) + * Copyright (c) 2018-2020 Jiaxun Yang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "cpu.h" +#include "hw/boards.h" +#include "hw/mips/loongson3_bootp.h" + +#define LOONGSON3_CORE_PER_NODE 4 + +static void init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq) +{ + struct efi_cpuinfo_loongson *c = g_cpuinfo; + + c->cputype = cpu_to_le32(Loongson_3A); + c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid); + if (cpu_freq > UINT_MAX) { + c->cpu_clock_freq = cpu_to_le32(UINT_MAX); + } else { + c->cpu_clock_freq = cpu_to_le32(cpu_freq); + } + + c->cpu_startup_core_id = cpu_to_le16(0); + c->nr_cpus = cpu_to_le32(current_machine->smp.cpus); + c->total_node = cpu_to_le32(DIV_ROUND_UP(current_machine->smp.cpus, + LOONGSON3_CORE_PER_NODE)); +} + +static void init_memory_map(void *g_map, uint64_t ram_size) +{ + struct efi_memory_map_loongson *emap = g_map; + + emap->nr_map = cpu_to_le32(2); + emap->mem_freq = cpu_to_le32(300000000); + + emap->map[0].node_id = cpu_to_le32(0); + emap->map[0].mem_type = cpu_to_le32(1); + emap->map[0].mem_start = cpu_to_le64(0x0); + emap->map[0].mem_size = cpu_to_le32(240); + + emap->map[1].node_id = cpu_to_le32(0); + emap->map[1].mem_type = cpu_to_le32(2); + emap->map[1].mem_start = cpu_to_le64(0x90000000); + emap->map[1].mem_size = cpu_to_le32((ram_size / MiB) - 256); +} + +static void init_system_loongson(void *g_system) +{ + struct system_loongson *s = g_system; + + s->ccnuma_smp = cpu_to_le32(0); + s->sing_double_channel = cpu_to_le32(1); + s->nr_uarts = cpu_to_le32(1); + s->uarts[0].iotype = cpu_to_le32(2); + s->uarts[0].int_offset = cpu_to_le32(2); + s->uarts[0].uartclk = cpu_to_le32(25000000); /* Random value */ + s->uarts[0].uart_base = cpu_to_le64(virt_memmap[VIRT_UART].base); +} + +static void init_irq_source(void *g_irq_source) +{ + struct irq_source_routing_table *irq_info = g_irq_source; + + irq_info->node_id = cpu_to_le32(0); + irq_info->PIC_type = cpu_to_le32(0); + irq_info->dma_mask_bits = cpu_to_le16(64); + irq_info->pci_mem_start_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_MMIO].base); + irq_info->pci_mem_end_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_MMIO].base + + virt_memmap[VIRT_PCIE_MMIO].size - 1); + irq_info->pci_io_start_addr = cpu_to_le64(virt_memmap[VIRT_PCIE_PIO].base); +} + +static void init_interface_info(void *g_interface) +{ + struct interface_info *interface = g_interface; + + interface->vers = cpu_to_le16(0x01); + strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0'); +} + +static void board_devices_info(void *g_board) +{ + struct board_devices *bd = g_board; + + strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0'); +} + +static void init_special_info(void *g_special) +{ + struct loongson_special_attribute *special = g_special; + + strpadcpy(special->special_name, 64, "2018-05-01", '\0'); +} + +void init_loongson_params(struct loongson_params *lp, void *p, + uint64_t cpu_freq, uint64_t ram_size) +{ + init_cpu_info(p, cpu_freq); + lp->cpu_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64); + + init_memory_map(p, ram_size); + lp->memory_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64); + + init_system_loongson(p); + lp->system_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct system_loongson), 64); + + init_irq_source(p); + lp->irq_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct irq_source_routing_table), 64); + + init_interface_info(p); + lp->interface_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct interface_info), 64); + + board_devices_info(p); + lp->boarddev_table_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct board_devices), 64); + + init_special_info(p); + lp->special_offset = cpu_to_le64((uintptr_t)p - (uintptr_t)lp); + p += ROUND_UP(sizeof(struct loongson_special_attribute), 64); +} + +void init_reset_system(struct efi_reset_system_t *reset) +{ + reset->Shutdown = cpu_to_le64(0xffffffffbfc000a8); + reset->ResetCold = cpu_to_le64(0xffffffffbfc00080); + reset->ResetWarm = cpu_to_le64(0xffffffffbfc00080); +} diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h new file mode 100644 index 0000000000..09f8480abf --- /dev/null +++ b/hw/mips/loongson3_bootp.h @@ -0,0 +1,241 @@ +/* + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) data structures + * defined at arch/mips/include/asm/mach-loongson64/boot_param.h in Linux kernel + * + * Copyright (c) 2017-2020 Huacai Chen (chenhc@lemote.com) + * Copyright (c) 2017-2020 Jiaxun Yang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 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 . + */ + +#ifndef HW_MIPS_LOONGSON3_BOOTP_H +#define HW_MIPS_LOONGSON3_BOOTP_H + +struct efi_memory_map_loongson { + uint16_t vers; /* version of efi_memory_map */ + uint32_t nr_map; /* number of memory_maps */ + uint32_t mem_freq; /* memory frequence */ + struct mem_map { + uint32_t node_id; /* node_id which memory attached to */ + uint32_t mem_type; /* system memory, pci memory, pci io, etc. */ + uint64_t mem_start; /* memory map start address */ + uint32_t mem_size; /* each memory_map size, not the total size */ + } map[128]; +} QEMU_PACKED; + +enum loongson_cpu_type { + Legacy_2E = 0x0, + Legacy_2F = 0x1, + Legacy_3A = 0x2, + Legacy_3B = 0x3, + Legacy_1A = 0x4, + Legacy_1B = 0x5, + Legacy_2G = 0x6, + Legacy_2H = 0x7, + Loongson_1A = 0x100, + Loongson_1B = 0x101, + Loongson_2E = 0x200, + Loongson_2F = 0x201, + Loongson_2G = 0x202, + Loongson_2H = 0x203, + Loongson_3A = 0x300, + Loongson_3B = 0x301 +}; + +/* + * Capability and feature descriptor structure for MIPS CPU + */ +struct efi_cpuinfo_loongson { + uint16_t vers; /* version of efi_cpuinfo_loongson */ + uint32_t processor_id; /* PRID, e.g. 6305, 6306 */ + uint32_t cputype; /* Loongson_3A/3B, etc. */ + uint32_t total_node; /* num of total numa nodes */ + uint16_t cpu_startup_core_id; /* Boot core id */ + uint16_t reserved_cores_mask; + uint32_t cpu_clock_freq; /* cpu_clock */ + uint32_t nr_cpus; + char cpuname[64]; +} QEMU_PACKED; + +#define MAX_UARTS 64 +struct uart_device { + uint32_t iotype; + uint32_t uartclk; + uint32_t int_offset; + uint64_t uart_base; +} QEMU_PACKED; + +#define MAX_SENSORS 64 +#define SENSOR_TEMPER 0x00000001 +#define SENSOR_VOLTAGE 0x00000002 +#define SENSOR_FAN 0x00000004 +struct sensor_device { + char name[32]; /* a formal name */ + char label[64]; /* a flexible description */ + uint32_t type; /* SENSOR_* */ + uint32_t id; /* instance id of a sensor-class */ + uint32_t fan_policy; /* step speed or constant speed */ + uint32_t fan_percent;/* only for constant speed policy */ + uint64_t base_addr; /* base address of device registers */ +} QEMU_PACKED; + +struct system_loongson { + uint16_t vers; /* version of system_loongson */ + uint32_t ccnuma_smp; /* 0: no numa; 1: has numa */ + uint32_t sing_double_channel;/* 1: single; 2: double */ + uint32_t nr_uarts; + struct uart_device uarts[MAX_UARTS]; + uint32_t nr_sensors; + struct sensor_device sensors[MAX_SENSORS]; + char has_ec; + char ec_name[32]; + uint64_t ec_base_addr; + char has_tcm; + char tcm_name[32]; + uint64_t tcm_base_addr; + uint64_t workarounds; + uint64_t of_dtb_addr; /* NULL if not support */ +} QEMU_PACKED; + +struct irq_source_routing_table { + uint16_t vers; + uint16_t size; + uint16_t rtr_bus; + uint16_t rtr_devfn; + uint32_t vendor; + uint32_t device; + uint32_t PIC_type; /* conform use HT or PCI to route to CPU-PIC */ + uint64_t ht_int_bit; /* 3A: 1<<24; 3B: 1<<16 */ + uint64_t ht_enable; /* irqs used in this PIC */ + uint32_t node_id; /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */ + uint64_t pci_mem_start_addr; + uint64_t pci_mem_end_addr; + uint64_t pci_io_start_addr; + uint64_t pci_io_end_addr; + uint64_t pci_config_addr; + uint16_t dma_mask_bits; + uint16_t dma_noncoherent; +} QEMU_PACKED; + +struct interface_info { + uint16_t vers; /* version of the specificition */ + uint16_t size; + uint8_t flag; + char description[64]; +} QEMU_PACKED; + +#define MAX_RESOURCE_NUMBER 128 +struct resource_loongson { + uint64_t start; /* resource start address */ + uint64_t end; /* resource end address */ + char name[64]; + uint32_t flags; +}; + +struct archdev_data {}; /* arch specific additions */ + +struct board_devices { + char name[64]; /* hold the device name */ + uint32_t num_resources; /* number of device_resource */ + /* for each device's resource */ + struct resource_loongson resource[MAX_RESOURCE_NUMBER]; + /* arch specific additions */ + struct archdev_data archdata; +}; + +struct loongson_special_attribute { + uint16_t vers; /* version of this special */ + char special_name[64]; /* special_atribute_name */ + uint32_t loongson_special_type; /* type of special device */ + /* for each device's resource */ + struct resource_loongson resource[MAX_RESOURCE_NUMBER]; +}; + +struct loongson_params { + uint64_t memory_offset; /* efi_memory_map_loongson struct offset */ + uint64_t cpu_offset; /* efi_cpuinfo_loongson struct offset */ + uint64_t system_offset; /* system_loongson struct offset */ + uint64_t irq_offset; /* irq_source_routing_table struct offset */ + uint64_t interface_offset; /* interface_info struct offset */ + uint64_t special_offset; /* loongson_special_attribute struct offset */ + uint64_t boarddev_table_offset; /* board_devices offset */ +}; + +struct smbios_tables { + uint16_t vers; /* version of smbios */ + uint64_t vga_bios; /* vga_bios address */ + struct loongson_params lp; +}; + +struct efi_reset_system_t { + uint64_t ResetCold; + uint64_t ResetWarm; + uint64_t ResetType; + uint64_t Shutdown; + uint64_t DoSuspend; /* NULL if not support */ +}; + +struct efi_loongson { + uint64_t mps; /* MPS table */ + uint64_t acpi; /* ACPI table (IA64 ext 0.71) */ + uint64_t acpi20; /* ACPI table (ACPI 2.0) */ + struct smbios_tables smbios; /* SM BIOS table */ + uint64_t sal_systab; /* SAL system table */ + uint64_t boot_info; /* boot info table */ +}; + +struct boot_params { + struct efi_loongson efi; + struct efi_reset_system_t reset_system; +}; + +/* Overall MMIO & Memory layout */ +enum { + VIRT_LOWMEM, + VIRT_PM, + VIRT_FW_CFG, + VIRT_RTC, + VIRT_PCIE_PIO, + VIRT_PCIE_ECAM, + VIRT_BIOS_ROM, + VIRT_UART, + VIRT_LIOINTC, + VIRT_PCIE_MMIO, + VIRT_HIGHMEM +}; + +/* Low MEM layout for QEMU kernel loader */ +enum { + LOADER_KERNEL, + LOADER_INITRD, + LOADER_CMDLINE +}; + +/* BIOS ROM layout for QEMU kernel loader */ +enum { + LOADER_BOOTROM, + LOADER_PARAM, +}; + +struct MemmapEntry { + hwaddr base; + hwaddr size; +}; + +extern const struct MemmapEntry virt_memmap[]; +void init_loongson_params(struct loongson_params *lp, void *p, + uint64_t cpu_freq, uint64_t ram_size); +void init_reset_system(struct efi_reset_system_t *reset); + +#endif diff --git a/hw/mips/meson.build b/hw/mips/meson.build index ca5e4d0f94..b06329f7ff 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -2,6 +2,7 @@ mips_ss = ss.source_set() mips_ss.add(files('mips_int.c')) mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) +mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c')) mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c')) mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c')) From c76b409fef19dc60a48f02a8e12e7fb46b07caf7 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Mon, 27 Apr 2020 17:33:14 +0800 Subject: [PATCH 26/35] hw/mips: Add Loongson-3 machine support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Loongson-3 based machine support, it use liointc as the interrupt controler and use GPEX as the pci controller. Currently it can work with both TCG and KVM. As the machine model is not based on any exiting physical hardware, the name of the machine is "loongson3-virt". It may be superseded in future by a real machine model. If this happens, then a regular deprecation procedure shall occur for "loongson3-virt" machine. We now already have a full functional Linux kernel (based on Linux-5.4.x LTS) here: https://github.com/chenhuacai/linux Of course the upstream kernel is also usable (the kvm host side and guest side have both been upstream in Linux-5.9): https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git How to use QEMU/Loongson-3? 1, Download kernel source from the above URL; 2, Build a kernel with arch/mips/configs/loongson3_defconfig; 3, Boot a Loongson-3A4000 host with this kernel (for KVM mode); 4, Build QEMU-master with this patchset; 5, modprobe kvm (only necessary for KVM mode); 6, Use QEMU with TCG: qemu-system-mips64el -M loongson3-virt,accel=tcg -cpu Loongson-3A1000 -kernel -append ... Use QEMU with KVM: qemu-system-mips64el -M loongson3-virt,accel=kvm -cpu Loongson-3A4000 -kernel -append ... The "-cpu" parameter is optional here and QEMU will use the correct type for TCG/KVM automatically. Co-developed-by: Jiaxun Yang Signed-off-by: Huacai Chen Signed-off-by: Jiaxun Yang Message-Id: <20201221110538.3186646-5-chenhuacai@kernel.org> Reviewed-by: Philippe Mathieu-Daudé [PMD: Set TYPE_LOONGSON_MACHINE instance_size in TypeInfo, select FW_CFG_MIPS in Kconfig] Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + default-configs/devices/mips64el-softmmu.mak | 1 + hw/mips/Kconfig | 12 + hw/mips/loongson3_virt.c | 638 +++++++++++++++++++ hw/mips/meson.build | 2 +- 5 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 hw/mips/loongson3_virt.c diff --git a/MAINTAINERS b/MAINTAINERS index 29c5e3b13c..da3bd3f752 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1161,6 +1161,7 @@ S: Maintained F: hw/intc/loongson_liointc.c F: hw/mips/loongson3_bootp.c F: hw/mips/loongson3_bootp.h +F: hw/mips/loongson3_virt.c Boston M: Paul Burton diff --git a/default-configs/devices/mips64el-softmmu.mak b/default-configs/devices/mips64el-softmmu.mak index 9f8a3ef156..26c660a05c 100644 --- a/default-configs/devices/mips64el-softmmu.mak +++ b/default-configs/devices/mips64el-softmmu.mak @@ -3,6 +3,7 @@ include mips-softmmu-common.mak CONFIG_IDE_VIA=y CONFIG_FULOONG=y +CONFIG_LOONGSON3V=y CONFIG_ATI_VGA=y CONFIG_RTL8139_PCI=y CONFIG_JAZZ=y diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 64ef42dd3f..aadd436bf4 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -32,6 +32,18 @@ config FULOONG bool select PCI_BONITO +config LOONGSON3V + bool + imply VIRTIO_VGA + imply QXL if SPICE + select SERIAL + select GOLDFISH_RTC + select LOONGSON_LIOINTC + select PCI_DEVICES + select PCI_EXPRESS_GENERIC_BRIDGE + select MSI_NONBROKEN + select FW_CFG_MIPS + config MIPS_CPS bool select PTIMER diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c new file mode 100644 index 0000000000..d4a82fa536 --- /dev/null +++ b/hw/mips/loongson3_virt.c @@ -0,0 +1,638 @@ +/* + * Generic Loongson-3 Platform support + * + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com) + * Copyright (c) 2018-2020 Jiaxun Yang + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 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 . + */ + +/* + * Generic virtualized PC Platform based on Loongson-3 CPU (MIPS64R2 with + * extensions, 800~2000MHz) + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/units.h" +#include "qemu/cutils.h" +#include "qemu/datadir.h" +#include "qapi/error.h" +#include "cpu.h" +#include "elf.h" +#include "kvm_mips.h" +#include "hw/boards.h" +#include "hw/char/serial.h" +#include "hw/intc/loongson_liointc.h" +#include "hw/mips/mips.h" +#include "hw/mips/cpudevs.h" +#include "hw/mips/fw_cfg.h" +#include "hw/mips/loongson3_bootp.h" +#include "hw/misc/unimp.h" +#include "hw/intc/i8259.h" +#include "hw/loader.h" +#include "hw/isa/superio.h" +#include "hw/pci/msi.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "hw/pci-host/gpex.h" +#include "hw/usb.h" +#include "net/net.h" +#include "exec/address-spaces.h" +#include "sysemu/kvm.h" +#include "sysemu/qtest.h" +#include "sysemu/reset.h" +#include "sysemu/runstate.h" +#include "qemu/log.h" +#include "qemu/error-report.h" + +#define PM_CNTL_MODE 0x10 + +#define LOONGSON_MAX_VCPUS 16 + +/* + * Loongson-3's virtual machine BIOS can be obtained here: + * 1, https://github.com/loongson-community/firmware-nonfree + * 2, http://dev.lemote.com:8000/files/firmware/UEFI/KVM/bios_loongson3.bin + */ +#define LOONGSON3_BIOSNAME "bios_loongson3.bin" + +#define UART_IRQ 0 +#define RTC_IRQ 1 +#define PCIE_IRQ_BASE 2 + +const struct MemmapEntry virt_memmap[] = { + [VIRT_LOWMEM] = { 0x00000000, 0x10000000 }, + [VIRT_PM] = { 0x10080000, 0x100 }, + [VIRT_FW_CFG] = { 0x10080100, 0x100 }, + [VIRT_RTC] = { 0x10081000, 0x1000 }, + [VIRT_PCIE_PIO] = { 0x18000000, 0x80000 }, + [VIRT_PCIE_ECAM] = { 0x1a000000, 0x2000000 }, + [VIRT_BIOS_ROM] = { 0x1fc00000, 0x200000 }, + [VIRT_UART] = { 0x1fe001e0, 0x8 }, + [VIRT_LIOINTC] = { 0x3ff01400, 0x64 }, + [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 }, + [VIRT_HIGHMEM] = { 0x80000000, 0x0 }, /* Variable */ +}; + +static const struct MemmapEntry loader_memmap[] = { + [LOADER_KERNEL] = { 0x00000000, 0x4000000 }, + [LOADER_INITRD] = { 0x04000000, 0x0 }, /* Variable */ + [LOADER_CMDLINE] = { 0x0ff00000, 0x100000 }, +}; + +static const struct MemmapEntry loader_rommap[] = { + [LOADER_BOOTROM] = { 0x1fc00000, 0x1000 }, + [LOADER_PARAM] = { 0x1fc01000, 0x10000 }, +}; + +struct LoongsonMachineState { + MachineState parent_obj; + MemoryRegion *pio_alias; + MemoryRegion *mmio_alias; + MemoryRegion *ecam_alias; +}; +typedef struct LoongsonMachineState LoongsonMachineState; + +#define TYPE_LOONGSON_MACHINE MACHINE_TYPE_NAME("loongson3-virt") +DECLARE_INSTANCE_CHECKER(LoongsonMachineState, LOONGSON_MACHINE, TYPE_LOONGSON_MACHINE) + +static struct _loaderparams { + uint64_t cpu_freq; + uint64_t ram_size; + const char *kernel_cmdline; + const char *kernel_filename; + const char *initrd_filename; + uint64_t kernel_entry; + uint64_t a0, a1, a2; +} loaderparams; + +static uint64_t loongson3_pm_read(void *opaque, hwaddr addr, unsigned size) +{ + return 0; +} + +static void loongson3_pm_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + if (addr != PM_CNTL_MODE) { + return; + } + + switch (val) { + case 0x00: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; + case 0xff: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + return; + default: + return; + } +} + +static const MemoryRegionOps loongson3_pm_ops = { + .read = loongson3_pm_read, + .write = loongson3_pm_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 1 + } +}; + +#define DEF_LOONGSON3_FREQ (800 * 1000 * 1000) + +static uint64_t get_cpu_freq_hz(void) +{ +#ifdef CONFIG_KVM + int ret; + uint64_t freq; + struct kvm_one_reg freq_reg = { + .id = KVM_REG_MIPS_COUNT_HZ, + .addr = (uintptr_t)(&freq) + }; + + if (kvm_enabled()) { + ret = kvm_vcpu_ioctl(first_cpu, KVM_GET_ONE_REG, &freq_reg); + if (ret >= 0) { + return freq * 2; + } + } +#endif + return DEF_LOONGSON3_FREQ; +} + +static void init_boot_param(void) +{ + static void *p; + struct boot_params *bp; + + p = g_malloc0(loader_rommap[LOADER_PARAM].size); + bp = p; + + bp->efi.smbios.vers = cpu_to_le16(1); + init_reset_system(&(bp->reset_system)); + p += ROUND_UP(sizeof(struct boot_params), 64); + init_loongson_params(&(bp->efi.smbios.lp), p, + loaderparams.cpu_freq, loaderparams.ram_size); + + rom_add_blob_fixed("params_rom", bp, + loader_rommap[LOADER_PARAM].size, + loader_rommap[LOADER_PARAM].base); + + g_free(bp); + + loaderparams.a2 = cpu_mips_phys_to_kseg0(NULL, + loader_rommap[LOADER_PARAM].base); +} + +static void init_boot_rom(void) +{ + const unsigned int boot_code[] = { + 0x40086000, /* mfc0 t0, CP0_STATUS */ + 0x240900E4, /* li t1, 0xe4 #set kx, sx, ux, erl */ + 0x01094025, /* or t0, t0, t1 */ + 0x3C090040, /* lui t1, 0x40 #set bev */ + 0x01094025, /* or t0, t0, t1 */ + 0x40886000, /* mtc0 t0, CP0_STATUS */ + 0x00000000, + 0x40806800, /* mtc0 zero, CP0_CAUSE */ + 0x00000000, + 0x400A7801, /* mfc0 t2, $15, 1 */ + 0x314A00FF, /* andi t2, 0x0ff */ + 0x3C089000, /* dli t0, 0x900000003ff01000 */ + 0x00084438, + 0x35083FF0, + 0x00084438, + 0x35081000, + 0x314B0003, /* andi t3, t2, 0x3 #local cpuid */ + 0x000B5A00, /* sll t3, 8 */ + 0x010B4025, /* or t0, t0, t3 */ + 0x314C000C, /* andi t4, t2, 0xc #node id */ + 0x000C62BC, /* dsll t4, 42 */ + 0x010C4025, /* or t0, t0, t4 */ + /* WaitForInit: */ + 0xDD020020, /* ld v0, FN_OFF(t0) #FN_OFF 0x020 */ + 0x1040FFFE, /* beqz v0, WaitForInit */ + 0x00000000, /* nop */ + 0xDD1D0028, /* ld sp, SP_OFF(t0) #FN_OFF 0x028 */ + 0xDD1C0030, /* ld gp, GP_OFF(t0) #FN_OFF 0x030 */ + 0xDD050038, /* ld a1, A1_OFF(t0) #FN_OFF 0x038 */ + 0x00400008, /* jr v0 #byebye */ + 0x00000000, /* nop */ + 0x1000FFFF, /* 1: b 1b */ + 0x00000000, /* nop */ + + /* Reset */ + 0x3C0C9000, /* dli t0, 0x9000000010080010 */ + 0x358C0000, + 0x000C6438, + 0x358C1008, + 0x000C6438, + 0x358C0010, + 0x240D0000, /* li t1, 0x00 */ + 0xA18D0000, /* sb t1, (t0) */ + 0x1000FFFF, /* 1: b 1b */ + 0x00000000, /* nop */ + + /* Shutdown */ + 0x3C0C9000, /* dli t0, 0x9000000010080010 */ + 0x358C0000, + 0x000C6438, + 0x358C1008, + 0x000C6438, + 0x358C0010, + 0x240D00FF, /* li t1, 0xff */ + 0xA18D0000, /* sb t1, (t0) */ + 0x1000FFFF, /* 1: b 1b */ + 0x00000000 /* nop */ + }; + + rom_add_blob_fixed("boot_rom", boot_code, sizeof(boot_code), + loader_rommap[LOADER_BOOTROM].base); +} + +static void fw_cfg_boot_set(void *opaque, const char *boot_device, + Error **errp) +{ + fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + +static void fw_conf_init(unsigned long ram_size) +{ + FWCfgState *fw_cfg; + hwaddr cfg_addr = virt_memmap[VIRT_FW_CFG].base; + + fw_cfg = fw_cfg_init_mem_wide(cfg_addr, cfg_addr + 8, 8, 0, NULL); + fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)current_machine->smp.cpus); + fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)current_machine->smp.max_cpus); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1); + fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz()); + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); +} + +static int set_prom_cmdline(ram_addr_t initrd_offset, long initrd_size) +{ + int ret = 0; + void *cmdline_buf; + hwaddr cmdline_vaddr; + unsigned int *parg_env; + + /* Allocate cmdline_buf for command line. */ + cmdline_buf = g_malloc0(loader_memmap[LOADER_CMDLINE].size); + cmdline_vaddr = cpu_mips_phys_to_kseg0(NULL, + loader_memmap[LOADER_CMDLINE].base); + + /* + * Layout of cmdline_buf looks like this: + * argv[0], argv[1], 0, env[0], env[1], ... env[i], 0, + * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0 + */ + parg_env = (void *)cmdline_buf; + + ret = (3 + 1) * 4; + *parg_env++ = cmdline_vaddr + ret; + ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "g")); + + /* argv1 */ + *parg_env++ = cmdline_vaddr + ret; + if (initrd_size > 0) + ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, + "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", + cpu_mips_phys_to_kseg0(NULL, initrd_offset), + initrd_size, loaderparams.kernel_cmdline)); + else + ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "%s", + loaderparams.kernel_cmdline)); + + /* argv2 */ + *parg_env++ = cmdline_vaddr + 4 * ret; + + rom_add_blob_fixed("cmdline", cmdline_buf, + loader_memmap[LOADER_CMDLINE].size, + loader_memmap[LOADER_CMDLINE].base); + + g_free(cmdline_buf); + + loaderparams.a0 = 2; + loaderparams.a1 = cmdline_vaddr; + + return 0; +} + +static uint64_t load_kernel(CPUMIPSState *env) +{ + long kernel_size; + ram_addr_t initrd_offset; + uint64_t kernel_entry, kernel_low, kernel_high, initrd_size; + + kernel_size = load_elf(loaderparams.kernel_filename, NULL, + cpu_mips_kseg0_to_phys, NULL, + (uint64_t *)&kernel_entry, + (uint64_t *)&kernel_low, (uint64_t *)&kernel_high, + NULL, 0, EM_MIPS, 1, 0); + if (kernel_size < 0) { + error_report("could not load kernel '%s': %s", + loaderparams.kernel_filename, + load_elf_strerror(kernel_size)); + exit(1); + } + + /* load initrd */ + initrd_size = 0; + initrd_offset = 0; + if (loaderparams.initrd_filename) { + initrd_size = get_image_size(loaderparams.initrd_filename); + if (initrd_size > 0) { + initrd_offset = MAX(loader_memmap[LOADER_INITRD].base, + ROUND_UP(kernel_high, INITRD_PAGE_SIZE)); + + if (initrd_offset + initrd_size > loaderparams.ram_size) { + error_report("memory too small for initial ram disk '%s'", + loaderparams.initrd_filename); + exit(1); + } + + initrd_size = load_image_targphys(loaderparams.initrd_filename, + initrd_offset, + loaderparams.ram_size - initrd_offset); + } + + if (initrd_size == (target_ulong) -1) { + error_report("could not load initial ram disk '%s'", + loaderparams.initrd_filename); + exit(1); + } + } + + /* Setup prom cmdline. */ + set_prom_cmdline(initrd_offset, initrd_size); + + return kernel_entry; +} + +static void main_cpu_reset(void *opaque) +{ + MIPSCPU *cpu = opaque; + CPUMIPSState *env = &cpu->env; + + cpu_reset(CPU(cpu)); + + /* Loongson-3 reset stuff */ + if (loaderparams.kernel_filename) { + if (cpu == MIPS_CPU(first_cpu)) { + env->active_tc.gpr[4] = loaderparams.a0; + env->active_tc.gpr[5] = loaderparams.a1; + env->active_tc.gpr[6] = loaderparams.a2; + env->active_tc.PC = loaderparams.kernel_entry; + } + env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); + } +} + +static inline void loongson3_virt_devices_init(MachineState *machine, + DeviceState *pic) +{ + int i; + qemu_irq irq; + PCIBus *pci_bus; + DeviceState *dev; + MemoryRegion *mmio_reg, *ecam_reg; + LoongsonMachineState *s = LOONGSON_MACHINE(machine); + + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + pci_bus = PCI_HOST_BRIDGE(dev)->bus; + + s->ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(s->ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, virt_memmap[VIRT_PCIE_ECAM].size); + memory_region_add_subregion(get_system_memory(), + virt_memmap[VIRT_PCIE_ECAM].base, + s->ecam_alias); + + s->mmio_alias = g_new0(MemoryRegion, 1); + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_init_alias(s->mmio_alias, OBJECT(dev), "pcie-mmio", + mmio_reg, virt_memmap[VIRT_PCIE_MMIO].base, + virt_memmap[VIRT_PCIE_MMIO].size); + memory_region_add_subregion(get_system_memory(), + virt_memmap[VIRT_PCIE_MMIO].base, + s->mmio_alias); + + s->pio_alias = g_new0(MemoryRegion, 1); + memory_region_init_alias(s->pio_alias, OBJECT(dev), "pcie-pio", + get_system_io(), 0, + virt_memmap[VIRT_PCIE_PIO].size); + memory_region_add_subregion(get_system_memory(), + virt_memmap[VIRT_PCIE_PIO].base, s->pio_alias); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base); + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); + gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i); + } + msi_nonbroken = true; + + pci_vga_init(pci_bus); + + if (defaults_enabled()) { + pci_create_simple(pci_bus, -1, "pci-ohci"); + usb_create_simple(usb_bus_find(-1), "usb-kbd"); + usb_create_simple(usb_bus_find(-1), "usb-tablet"); + } + + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (!nd->model) { + nd->model = g_strdup("virtio"); + } + + pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); + } +} + +static void mips_loongson3_virt_init(MachineState *machine) +{ + int i; + long bios_size; + MIPSCPU *cpu; + Clock *cpuclk; + CPUMIPSState *env; + DeviceState *liointc; + char *filename; + const char *kernel_cmdline = machine->kernel_cmdline; + const char *kernel_filename = machine->kernel_filename; + const char *initrd_filename = machine->initrd_filename; + ram_addr_t ram_size = machine->ram_size; + MemoryRegion *address_space_mem = get_system_memory(); + MemoryRegion *ram = g_new(MemoryRegion, 1); + MemoryRegion *bios = g_new(MemoryRegion, 1); + MemoryRegion *iomem = g_new(MemoryRegion, 1); + + /* TODO: TCG will support all CPU types */ + if (!kvm_enabled()) { + if (!machine->cpu_type) { + machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000"); + } + if (!strstr(machine->cpu_type, "Loongson-3A1000")) { + error_report("Loongson-3/TCG needs cpu type Loongson-3A1000"); + exit(1); + } + } else { + if (!machine->cpu_type) { + machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000"); + } + if (!strstr(machine->cpu_type, "Loongson-3A4000")) { + error_report("Loongson-3/KVM needs cpu type Loongson-3A4000"); + exit(1); + } + } + + if (ram_size < 512 * MiB) { + error_report("Loongson-3 machine needs at least 512MB memory"); + exit(1); + } + + /* + * The whole MMIO range among configure registers doesn't generate + * exception when accessing invalid memory. Create some unimplememted + * devices to emulate this feature. + */ + create_unimplemented_device("mmio fallback 0", 0x10000000, 256 * MiB); + create_unimplemented_device("mmio fallback 1", 0x30000000, 256 * MiB); + + liointc = qdev_new("loongson.liointc"); + sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal); + + sysbus_mmio_map(SYS_BUS_DEVICE(liointc), 0, virt_memmap[VIRT_LIOINTC].base); + + serial_mm_init(address_space_mem, virt_memmap[VIRT_UART].base, 0, + qdev_get_gpio_in(liointc, UART_IRQ), 115200, serial_hd(0), + DEVICE_NATIVE_ENDIAN); + + sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base, + qdev_get_gpio_in(liointc, RTC_IRQ)); + + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); + clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); + + for (i = 0; i < machine->smp.cpus; i++) { + int ip; + + /* init CPUs */ + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); + + /* Init internal devices */ + cpu_mips_irq_init_cpu(cpu); + cpu_mips_clock_init(cpu); + qemu_register_reset(main_cpu_reset, cpu); + + if (i >= 4) { + continue; /* Only node-0 can be connected to LIOINTC */ + } + + for (ip = 0; ip < 4 ; ip++) { + int pin = i * 4 + ip; + sysbus_connect_irq(SYS_BUS_DEVICE(liointc), + pin, cpu->env.irq[ip + 2]); + } + } + env = &MIPS_CPU(first_cpu)->env; + + /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */ + memory_region_init_rom(bios, NULL, "loongson3.bios", + virt_memmap[VIRT_BIOS_ROM].size, &error_fatal); + memory_region_init_alias(ram, NULL, "loongson3.lowmem", + machine->ram, 0, virt_memmap[VIRT_LOWMEM].size); + memory_region_init_io(iomem, NULL, &loongson3_pm_ops, + NULL, "loongson3_pm", virt_memmap[VIRT_PM].size); + + memory_region_add_subregion(address_space_mem, + virt_memmap[VIRT_LOWMEM].base, ram); + memory_region_add_subregion(address_space_mem, + virt_memmap[VIRT_BIOS_ROM].base, bios); + memory_region_add_subregion(address_space_mem, + virt_memmap[VIRT_HIGHMEM].base, machine->ram); + memory_region_add_subregion(address_space_mem, + virt_memmap[VIRT_PM].base, iomem); + + /* + * We do not support flash operation, just loading bios.bin as raw BIOS. + * Please use -L to set the BIOS path and -bios to set bios name. + */ + + if (kernel_filename) { + loaderparams.cpu_freq = get_cpu_freq_hz(); + loaderparams.ram_size = ram_size; + loaderparams.kernel_filename = kernel_filename; + loaderparams.kernel_cmdline = kernel_cmdline; + loaderparams.initrd_filename = initrd_filename; + loaderparams.kernel_entry = load_kernel(env); + + init_boot_rom(); + init_boot_param(); + } else { + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + machine->firmware ?: LOONGSON3_BIOSNAME); + if (filename) { + bios_size = load_image_targphys(filename, + virt_memmap[VIRT_BIOS_ROM].base, + virt_memmap[VIRT_BIOS_ROM].size); + g_free(filename); + } else { + bios_size = -1; + } + + if ((bios_size < 0 || bios_size > virt_memmap[VIRT_BIOS_ROM].size) && + !kernel_filename && !qtest_enabled()) { + error_report("Could not load MIPS bios '%s'", machine->firmware); + exit(1); + } + + fw_conf_init(ram_size); + } + + loongson3_virt_devices_init(machine, liointc); +} + +static void loongson3v_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Loongson-3 Virtualization Platform"; + mc->init = mips_loongson3_virt_init; + mc->block_default_type = IF_IDE; + mc->max_cpus = LOONGSON_MAX_VCPUS; + mc->default_ram_id = "loongson3.highram"; + mc->default_ram_size = 1600 * MiB; + mc->kvm_type = mips_kvm_type; + mc->minimum_page_bits = 14; +} + +static const TypeInfo loongson3_machine_types[] = { + { + .name = TYPE_LOONGSON_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(LoongsonMachineState), + .class_init = loongson3v_machine_class_init, + } +}; + +DEFINE_TYPES(loongson3_machine_types) diff --git a/hw/mips/meson.build b/hw/mips/meson.build index b06329f7ff..ee19cc204d 100644 --- a/hw/mips/meson.build +++ b/hw/mips/meson.build @@ -2,7 +2,7 @@ mips_ss = ss.source_set() mips_ss.add(files('mips_int.c')) mips_ss.add(when: 'CONFIG_FW_CFG_MIPS', if_true: files('fw_cfg.c')) mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c')) -mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c')) +mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 'loongson3_virt.c')) mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c')) mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c')) mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c')) From c7784e42c7cce358ba9b21231dffe376f670cd5f Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Mon, 21 Dec 2020 19:05:38 +0800 Subject: [PATCH 27/35] docs/system: Update MIPS machine documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update MIPS machine documentation to add Loongson-3 based machine description. Signed-off-by: Huacai Chen Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201221110538.3186646-6-chenhuacai@kernel.org> Signed-off-by: Philippe Mathieu-Daudé --- docs/system/target-mips.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst index cd2a931edf..138441bdec 100644 --- a/docs/system/target-mips.rst +++ b/docs/system/target-mips.rst @@ -84,6 +84,16 @@ The Fuloong 2E emulation supports: - RTL8139D as a network card chipset +The Loongson-3 virtual platform emulation supports: + +- Loongson 3A CPU + +- LIOINTC as interrupt controller + +- GPEX and virtio as peripheral devices + +- Both KVM and TCG supported + The mipssim pseudo board emulation provides an environment similar to what the proprietary MIPS emulator uses for running Linux. It supports: From dde989943b401aec3a063214278474d2f8c1a9de Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 15 Dec 2020 14:41:53 +0800 Subject: [PATCH 28/35] hw/mips: Make bootloader addresses unsigned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address should be unsigned anyway, otherwise it may carry calculations wrongly. Signed-off-by: Jiaxun Yang Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201215064200.28751-2-jiaxun.yang@flygoat.com> [PMD: Fixed typo and convert hw/mips/mipssim.c too] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 12 ++++++------ hw/mips/malta.c | 22 +++++++++++----------- hw/mips/mipssim.c | 8 ++++---- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index e5d0866906..804bef94cd 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -107,9 +107,9 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, va_end(ap); } -static int64_t load_kernel(CPUMIPSState *env) +static uint64_t load_kernel(CPUMIPSState *env) { - int64_t kernel_entry, kernel_high, initrd_size; + uint64_t kernel_entry, kernel_high, initrd_size; int index = 0; long kernel_size; ram_addr_t initrd_offset; @@ -118,8 +118,8 @@ static int64_t load_kernel(CPUMIPSState *env) kernel_size = load_elf(loaderparams.kernel_filename, NULL, cpu_mips_kseg0_to_phys, NULL, - (uint64_t *)&kernel_entry, NULL, - (uint64_t *)&kernel_high, NULL, + &kernel_entry, NULL, + &kernel_high, NULL, 0, EM_MIPS, 1, 0); if (kernel_size < 0) { error_report("could not load kernel '%s': %s", @@ -180,7 +180,7 @@ static int64_t load_kernel(CPUMIPSState *env) } static void write_bootloader(CPUMIPSState *env, uint8_t *base, - int64_t kernel_addr) + uint64_t kernel_addr) { uint32_t *p; @@ -299,7 +299,7 @@ static void mips_fuloong2e_init(MachineState *machine) MemoryRegion *bios = g_new(MemoryRegion, 1); long bios_size; uint8_t *spd_data; - int64_t kernel_entry; + uint64_t kernel_entry; PCIDevice *pci_dev; PCIBus *pci_bus; ISABus *isa_bus; diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 366f4fdfcd..7db009a3e9 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -616,8 +616,8 @@ static void network_init(PCIBus *pci_bus) } } -static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr, - int64_t kernel_entry) +static void write_bootloader_nanomips(uint8_t *base, uint64_t run_addr, + uint64_t kernel_entry) { uint16_t *p; @@ -840,8 +840,8 @@ static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr, * a2 - 32-bit address of the environment variables table * a3 - RAM size in bytes */ -static void write_bootloader(uint8_t *base, int64_t run_addr, - int64_t kernel_entry) +static void write_bootloader(uint8_t *base, uint64_t run_addr, + uint64_t kernel_entry) { uint32_t *p; @@ -1003,7 +1003,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, const char *string, ...) { va_list ap; - int32_t table_addr; + uint32_t table_addr; if (index >= ENVP_NB_ENTRIES) { return; @@ -1014,7 +1014,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, return; } - table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE; + table_addr = sizeof(uint32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE; prom_buf[index] = tswap32(ENVP_ADDR + table_addr); va_start(ap, string); @@ -1023,9 +1023,9 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, } /* Kernel */ -static int64_t load_kernel(void) +static uint64_t load_kernel(void) { - int64_t kernel_entry, kernel_high, initrd_size; + uint64_t kernel_entry, kernel_high, initrd_size; long kernel_size; ram_addr_t initrd_offset; int big_endian; @@ -1042,8 +1042,8 @@ static int64_t load_kernel(void) kernel_size = load_elf(loaderparams.kernel_filename, NULL, cpu_mips_kseg0_to_phys, NULL, - (uint64_t *)&kernel_entry, NULL, - (uint64_t *)&kernel_high, NULL, big_endian, EM_MIPS, + &kernel_entry, NULL, + &kernel_high, NULL, big_endian, EM_MIPS, 1, 0); if (kernel_size < 0) { error_report("could not load kernel '%s': %s", @@ -1234,7 +1234,7 @@ void mips_malta_init(MachineState *machine) MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1); const size_t smbus_eeprom_size = 8 * 256; uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size); - int64_t kernel_entry, bootloader_run_addr; + uint64_t kernel_entry, bootloader_run_addr; PCIBus *pci_bus; ISABus *isa_bus; qemu_irq cbus_irq, i8259_irq; diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index f2e6273525..f5d0da05aa 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -60,9 +60,9 @@ typedef struct ResetData { uint64_t vector; } ResetData; -static int64_t load_kernel(void) +static uint64_t load_kernel(void) { - int64_t entry, kernel_high, initrd_size; + uint64_t entry, kernel_high, initrd_size; long kernel_size; ram_addr_t initrd_offset; int big_endian; @@ -75,8 +75,8 @@ static int64_t load_kernel(void) kernel_size = load_elf(loaderparams.kernel_filename, NULL, cpu_mips_kseg0_to_phys, NULL, - (uint64_t *)&entry, NULL, - (uint64_t *)&kernel_high, NULL, big_endian, + &entry, NULL, + &kernel_high, NULL, big_endian, EM_MIPS, 1, 0); if (kernel_size < 0) { error_report("could not load kernel '%s': %s", From 5052b6e82ccad696f63b9e7107e49c53965f750c Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 15 Dec 2020 14:41:54 +0800 Subject: [PATCH 29/35] hw/mips/malta: Use address translation helper to calculate bootloader_run_addr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So it will sign extend adresses properly. Signed-off-by: Jiaxun Yang Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201215064200.28751-3-jiaxun.yang@flygoat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/malta.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 7db009a3e9..1fbb8a3220 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1302,9 +1302,9 @@ void mips_malta_init(MachineState *machine) /* For KVM we reserve 1MB of RAM for running bootloader */ if (kvm_enabled()) { ram_low_size -= 0x100000; - bootloader_run_addr = 0x40000000 + ram_low_size; + bootloader_run_addr = cpu_mips_kvm_um_phys_to_kseg0(NULL, ram_low_size); } else { - bootloader_run_addr = 0xbfc00000; + bootloader_run_addr = cpu_mips_phys_to_kseg0(NULL, RESET_ADDRESS); } /* Write a small bootloader to the flash location. */ From df055c65e47e4f255921b4125221b8a9f8fccc00 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 15 Dec 2020 14:41:55 +0800 Subject: [PATCH 30/35] hw/mips: Use address translation helper to handle ENVP_ADDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will signed extend vaddr properly. Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20201215064200.28751-4-jiaxun.yang@flygoat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 24 +++++++++--------- hw/mips/malta.c | 62 ++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 804bef94cd..8bc854130e 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -49,7 +49,8 @@ #define DEBUG_FULOONG2E_INIT -#define ENVP_ADDR 0x80002000l +#define ENVP_PADDR 0x2000 +#define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR) #define ENVP_NB_ENTRIES 16 #define ENVP_ENTRY_SIZE 256 @@ -100,7 +101,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, } table_addr = sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE; - prom_buf[index] = tswap32(ENVP_ADDR + table_addr); + prom_buf[index] = tswap32(ENVP_VADDR + table_addr); va_start(ap, string); vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap); @@ -172,8 +173,7 @@ static uint64_t load_kernel(CPUMIPSState *env) prom_set(prom_buf, index++, "modetty0=38400n8r"); prom_set(prom_buf, index++, NULL); - rom_add_blob_fixed("prom", prom_buf, prom_size, - cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR)); + rom_add_blob_fixed("prom", prom_buf, prom_size, ENVP_PADDR); g_free(prom_buf); return kernel_entry; @@ -199,14 +199,14 @@ static void write_bootloader(CPUMIPSState *env, uint8_t *base, stl_p(p++, 0x3c040000); /* ori a0, a0, 2 */ stl_p(p++, 0x34840002); - /* lui a1, high(ENVP_ADDR) */ - stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); - /* ori a1, a0, low(ENVP_ADDR) */ - stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); - /* lui a2, high(ENVP_ADDR + 8) */ - stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); - /* ori a2, a2, low(ENVP_ADDR + 8) */ - stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); + /* lui a1, high(ENVP_VADDR) */ + stl_p(p++, 0x3c050000 | ((ENVP_VADDR >> 16) & 0xffff)); + /* ori a1, a0, low(ENVP_VADDR) */ + stl_p(p++, 0x34a50000 | (ENVP_VADDR & 0xffff)); + /* lui a2, high(ENVP_VADDR + 8) */ + stl_p(p++, 0x3c060000 | (((ENVP_VADDR + 8) >> 16) & 0xffff)); + /* ori a2, a2, low(ENVP_VADDR + 8) */ + stl_p(p++, 0x34c60000 | ((ENVP_VADDR + 8) & 0xffff)); /* lui a3, high(env->ram_size) */ stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* ori a3, a3, low(env->ram_size) */ diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 1fbb8a3220..9afc0b427b 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -62,7 +62,8 @@ #include "hw/mips/cps.h" #include "hw/qdev-clock.h" -#define ENVP_ADDR 0x80002000l +#define ENVP_PADDR 0x2000 +#define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR) #define ENVP_NB_ENTRIES 16 #define ENVP_ENTRY_SIZE 256 @@ -656,29 +657,29 @@ static void write_bootloader_nanomips(uint8_t *base, uint64_t run_addr, /* li a0,2 */ } - stw_p(p++, 0xe3a0 | NM_HI1(ENVP_ADDR - 64)); + stw_p(p++, 0xe3a0 | NM_HI1(ENVP_VADDR - 64)); - stw_p(p++, NM_HI2(ENVP_ADDR - 64)); - /* lui sp,%hi(ENVP_ADDR - 64) */ + stw_p(p++, NM_HI2(ENVP_VADDR - 64)); + /* lui sp,%hi(ENVP_VADDR - 64) */ - stw_p(p++, 0x83bd); stw_p(p++, NM_LO(ENVP_ADDR - 64)); - /* ori sp,sp,%lo(ENVP_ADDR - 64) */ + stw_p(p++, 0x83bd); stw_p(p++, NM_LO(ENVP_VADDR - 64)); + /* ori sp,sp,%lo(ENVP_VADDR - 64) */ - stw_p(p++, 0xe0a0 | NM_HI1(ENVP_ADDR)); + stw_p(p++, 0xe0a0 | NM_HI1(ENVP_VADDR)); - stw_p(p++, NM_HI2(ENVP_ADDR)); - /* lui a1,%hi(ENVP_ADDR) */ + stw_p(p++, NM_HI2(ENVP_VADDR)); + /* lui a1,%hi(ENVP_VADDR) */ - stw_p(p++, 0x80a5); stw_p(p++, NM_LO(ENVP_ADDR)); - /* ori a1,a1,%lo(ENVP_ADDR) */ + stw_p(p++, 0x80a5); stw_p(p++, NM_LO(ENVP_VADDR)); + /* ori a1,a1,%lo(ENVP_VADDR) */ - stw_p(p++, 0xe0c0 | NM_HI1(ENVP_ADDR + 8)); + stw_p(p++, 0xe0c0 | NM_HI1(ENVP_VADDR + 8)); - stw_p(p++, NM_HI2(ENVP_ADDR + 8)); - /* lui a2,%hi(ENVP_ADDR + 8) */ + stw_p(p++, NM_HI2(ENVP_VADDR + 8)); + /* lui a2,%hi(ENVP_VADDR + 8) */ - stw_p(p++, 0x80c6); stw_p(p++, NM_LO(ENVP_ADDR + 8)); - /* ori a2,a2,%lo(ENVP_ADDR + 8) */ + stw_p(p++, 0x80c6); stw_p(p++, NM_LO(ENVP_VADDR + 8)); + /* ori a2,a2,%lo(ENVP_VADDR + 8) */ stw_p(p++, 0xe0e0 | NM_HI1(loaderparams.ram_low_size)); @@ -878,18 +879,18 @@ static void write_bootloader(uint8_t *base, uint64_t run_addr, stl_p(p++, 0x24040002); /* addiu a0, zero, 2 */ } - /* lui sp, high(ENVP_ADDR) */ - stl_p(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); - /* ori sp, sp, low(ENVP_ADDR) */ - stl_p(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); - /* lui a1, high(ENVP_ADDR) */ - stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); - /* ori a1, a1, low(ENVP_ADDR) */ - stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); - /* lui a2, high(ENVP_ADDR + 8) */ - stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); - /* ori a2, a2, low(ENVP_ADDR + 8) */ - stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); + /* lui sp, high(ENVP_VADDR) */ + stl_p(p++, 0x3c1d0000 | (((ENVP_VADDR - 64) >> 16) & 0xffff)); + /* ori sp, sp, low(ENVP_VADDR) */ + stl_p(p++, 0x37bd0000 | ((ENVP_VADDR - 64) & 0xffff)); + /* lui a1, high(ENVP_VADDR) */ + stl_p(p++, 0x3c050000 | ((ENVP_VADDR >> 16) & 0xffff)); + /* ori a1, a1, low(ENVP_VADDR) */ + stl_p(p++, 0x34a50000 | (ENVP_VADDR & 0xffff)); + /* lui a2, high(ENVP_VADDR + 8) */ + stl_p(p++, 0x3c060000 | (((ENVP_VADDR + 8) >> 16) & 0xffff)); + /* ori a2, a2, low(ENVP_VADDR + 8) */ + stl_p(p++, 0x34c60000 | ((ENVP_VADDR + 8) & 0xffff)); /* lui a3, high(ram_low_size) */ stl_p(p++, 0x3c070000 | (loaderparams.ram_low_size >> 16)); /* ori a3, a3, low(ram_low_size) */ @@ -1015,7 +1016,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, } table_addr = sizeof(uint32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE; - prom_buf[index] = tswap32(ENVP_ADDR + table_addr); + prom_buf[index] = tswap32(ENVP_VADDR + table_addr); va_start(ap, string); vsnprintf((char *)prom_buf + table_addr, ENVP_ENTRY_SIZE, string, ap); @@ -1122,8 +1123,7 @@ static uint64_t load_kernel(void) prom_set(prom_buf, prom_index++, "38400n8r"); prom_set(prom_buf, prom_index++, NULL); - rom_add_blob_fixed("prom", prom_buf, prom_size, - cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR)); + rom_add_blob_fixed("prom", prom_buf, prom_size, ENVP_PADDR); g_free(prom_buf); return kernel_entry; From 6fed2a8ea4f50377d9c4aee051c7e75d9d70de5d Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 24 Dec 2020 11:17:43 +0800 Subject: [PATCH 31/35] hw/mips/fuloong2e: Remove define DEBUG_FULOONG2E_INIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems useless.... Fixes: 051c190bce5 ("MIPS: Initial support of fulong mini pc (machine construction)") Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Huacai Chen Message-Id: <20201224031750.52146-2-jiaxun.yang@flygoat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 8bc854130e..c5a20b6462 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -47,8 +47,6 @@ #include "sysemu/reset.h" #include "qemu/error-report.h" -#define DEBUG_FULOONG2E_INIT - #define ENVP_PADDR 0x2000 #define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR) #define ENVP_NB_ENTRIES 16 From 94a37806c0269f9fa5554ebde3ffb141f22e187d Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 24 Dec 2020 11:17:44 +0800 Subject: [PATCH 32/35] hw/mips/fuloong2e: Replace faulty documentation links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Websites are downing, but GitHub may last forever. Loongson even doesn't recogonize 2E as their products nowadays.. Signed-off-by: Jiaxun Yang Tested-by: Philippe Mathieu-Daudé Reviewed-by: Huacai Chen Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201224031750.52146-3-jiaxun.yang@flygoat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index c5a20b6462..09169a9aa9 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -14,8 +14,8 @@ * Fuloong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz) * https://www.linux-mips.org/wiki/Fuloong_2E * - * Loongson 2e user manual: - * http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf + * Loongson 2e manuals: + * https://github.com/loongson-community/docs/tree/master/2E */ #include "qemu/osdep.h" @@ -60,14 +60,7 @@ * PMON is not part of qemu and released with BSD license, anyone * who want to build a pmon binary please first git-clone the source * from the git repository at: - * http://www.loongson.cn/support/git/pmon - * Then follow the "Compile Guide" available at: - * http://dev.lemote.com/code/pmon - * - * Notes: - * 1, don't use the source at http://dev.lemote.com/http_git/pmon.git - * 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware" - * in the "Compile Guide". + * https://github.com/loongson-community/pmon */ #define FULOONG_BIOSNAME "pmon_2e.bin" From c0809fcfac3cf599d69f7e4610856a786d78ccad Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 24 Dec 2020 11:17:47 +0800 Subject: [PATCH 33/35] hw/mips/fuloong2e: Remove unused env entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit modetty is not handled by kernel and the parameter here seems unreasonable. Signed-off-by: Jiaxun Yang Message-Id: <20201224031750.52146-6-jiaxun.yang@flygoat.com> Reviewed-by: Philippe Mathieu-Daudé [PMD: Do not remove busclock] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 09169a9aa9..9b44ac6cf9 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -161,7 +161,6 @@ static uint64_t load_kernel(CPUMIPSState *env) prom_set(prom_buf, index++, "busclock=33000000"); prom_set(prom_buf, index++, "cpuclock=100000000"); prom_set(prom_buf, index++, "memsize=%"PRIi64, loaderparams.ram_size / MiB); - prom_set(prom_buf, index++, "modetty0=38400n8r"); prom_set(prom_buf, index++, NULL); rom_add_blob_fixed("prom", prom_buf, prom_size, ENVP_PADDR); From e41f27ec2a0c29a7b016af16992cf6e642a54002 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 24 Dec 2020 11:17:48 +0800 Subject: [PATCH 34/35] hw/mips/fuloong2e: Correct cpuclock in PROM environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed in 3ca7639ff00 ("hw/mips/fuloong2e: Set CPU frequency to 533 MHz"), we need to tell the kernel the correct clock. Fixes: 3ca7639ff00 ("hw/mips/fuloong2e: Set CPU frequency to 533 MHz"). Signed-off-by: Jiaxun Yang Reviewed-by: Huacai Chen Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20201224031750.52146-7-jiaxun.yang@flygoat.com> [PMD: Reworded] Signed-off-by: Philippe Mathieu-Daudé --- hw/mips/fuloong2e.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index 9b44ac6cf9..29805242ca 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -99,7 +99,7 @@ static void GCC_FMT_ATTR(3, 4) prom_set(uint32_t *prom_buf, int index, va_end(ap); } -static uint64_t load_kernel(CPUMIPSState *env) +static uint64_t load_kernel(MIPSCPU *cpu) { uint64_t kernel_entry, kernel_high, initrd_size; int index = 0; @@ -159,7 +159,7 @@ static uint64_t load_kernel(CPUMIPSState *env) /* Setup minimum environment variables */ prom_set(prom_buf, index++, "busclock=33000000"); - prom_set(prom_buf, index++, "cpuclock=100000000"); + prom_set(prom_buf, index++, "cpuclock=%u", clock_get_hz(cpu->clock)); prom_set(prom_buf, index++, "memsize=%"PRIi64, loaderparams.ram_size / MiB); prom_set(prom_buf, index++, NULL); @@ -330,7 +330,7 @@ static void mips_fuloong2e_init(MachineState *machine) loaderparams.kernel_filename = kernel_filename; loaderparams.kernel_cmdline = kernel_cmdline; loaderparams.initrd_filename = initrd_filename; - kernel_entry = load_kernel(env); + kernel_entry = load_kernel(cpu); write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry); } else { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, From 457027298749333047bf81a856ce95ea5f9dccd9 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 24 Dec 2020 11:17:50 +0800 Subject: [PATCH 35/35] tests/acceptance: Test boot_linux_console for fuloong2e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel comes from debian archive so it's trusted. Invoking the test can be done as follows: $ avocado --show=app,console run -t machine:fuloong2e tests/acceptance/ (1/1) tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_mips64el_fuloong2e: console: [ 0.000000] Initializing cgroup subsys cpuset console: [ 0.000000] Initializing cgroup subsys cpu console: [ 0.000000] Initializing cgroup subsys cpuacct console: [ 0.000000] Linux version 3.16.0-6-loongson-2e (debian-kernel@lists.debian.org) (gcc version 4.8.4 (Debian 4.8.4-1) ) #1 Debian 3.16.56-1+deb8u1 (2018-05-08) console: [ 0.000000] memsize=256, highmemsize=0 console: [ 0.000000] CpuClock = 533080000 console: [ 0.000000] bootconsole [early0] enabled console: [ 0.000000] CPU0 revision is: 00006302 (ICT Loongson-2) console: [ 0.000000] FPU revision is: 00000501 console: [ 0.000000] Checking for the multiply/shift bug... no. console: [ 0.000000] Checking for the daddiu bug... no. console: [ 0.000000] Determined physical RAM map: console: [ 0.000000] memory: 0000000010000000 @ 0000000000000000 (usable) console: [ 0.000000] memory: 0000000004000000 @ 0000000010000000 (reserved) console: [ 0.000000] memory: 0000000003ffffff @ 000000001c000001 (reserved) console: [ 0.000000] Initrd not found or empty - disabling initrd console: [ 0.000000] Zone ranges: console: [ 0.000000] DMA [mem 0x00000000-0x00ffffff] console: [ 0.000000] Normal [mem 0x01000000-0x0fffffff] console: [ 0.000000] Movable zone start for each node console: [ 0.000000] Early memory node ranges console: [ 0.000000] node 0: [mem 0x00000000-0x0fffffff] console: [ 0.000000] Reserving 0MB of memory at 0MB for crashkernel console: [ 0.000000] Primary instruction cache 64kB, VIPT, direct mapped, linesize 32 bytes. console: [ 0.000000] Primary data cache 64kB, 4-way, VIPT, no aliases, linesize 32 bytes console: [ 0.000000] Unified secondary cache 512kB 4-way, linesize 32 bytes. console: [ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16327 console: [ 0.000000] Kernel command line: printk.time=0 console=ttyS0 PASS (2.27 s) Signed-off-by: Jiaxun Yang Reviewed-by: Wainer dos Santos Moschetta Reviewed-by: Willian Rampazzo Reviewed-by: Huacai Chen Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-Id: <20201224031750.52146-9-jiaxun.yang@flygoat.com> [PMD: Added command line example] Signed-off-by: Philippe Mathieu-Daudé --- tests/acceptance/boot_linux_console.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py index cc6ec0f8c1..fb41bb7144 100644 --- a/tests/acceptance/boot_linux_console.py +++ b/tests/acceptance/boot_linux_console.py @@ -170,6 +170,27 @@ class BootLinuxConsole(LinuxKernelTest): console_pattern = 'Kernel command line: %s' % kernel_command_line self.wait_for_console_pattern(console_pattern) + def test_mips64el_fuloong2e(self): + """ + :avocado: tags=arch:mips64el + :avocado: tags=machine:fuloong2e + :avocado: tags=endian:little + """ + deb_url = ('http://archive.debian.org/debian/pool/main/l/linux/' + 'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb') + deb_hash = 'd04d446045deecf7b755ef576551de0c4184dd44' + deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash) + kernel_path = self.extract_from_deb(deb_path, + '/boot/vmlinux-3.16.0-6-loongson-2e') + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + console_pattern = 'Kernel command line: %s' % kernel_command_line + self.wait_for_console_pattern(console_pattern) + def test_mips_malta_cpio(self): """ :avocado: tags=arch:mips