diff options
Diffstat (limited to 'hw/sparc64')
-rw-r--r-- | hw/sparc64/sparc64.c | 85 | ||||
-rw-r--r-- | hw/sparc64/sun4u.c | 109 | ||||
-rw-r--r-- | hw/sparc64/trace-events | 18 |
3 files changed, 138 insertions, 74 deletions
diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index 95a06f00b2..408388945e 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -28,25 +28,9 @@ #include "hw/char/serial.h" #include "hw/sparc/sparc64.h" #include "qemu/timer.h" +#include "trace.h" -//#define DEBUG_IRQ -//#define DEBUG_TIMER - -#ifdef DEBUG_IRQ -#define CPUIRQ_DPRINTF(fmt, ...) \ - do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0) -#else -#define CPUIRQ_DPRINTF(fmt, ...) -#endif - -#ifdef DEBUG_TIMER -#define TIMER_DPRINTF(fmt, ...) \ - do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0) -#else -#define TIMER_DPRINTF(fmt, ...) -#endif - #define TICK_MAX 0x7fffffffffffffffULL void cpu_check_irqs(CPUSPARCState *env) @@ -73,8 +57,7 @@ void cpu_check_irqs(CPUSPARCState *env) is (2 << psrpil). */ if (pil < (2 << env->psrpil)) { if (cs->interrupt_request & CPU_INTERRUPT_HARD) { - CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n", - env->interrupt_index); + trace_sparc64_cpu_check_irqs_reset_irq(env->interrupt_index); env->interrupt_index = 0; cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } @@ -92,22 +75,21 @@ void cpu_check_irqs(CPUSPARCState *env) if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) { - CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d " - "current %x >= pending %x\n", - env->tl, cpu_tsptr(env)->tt, new_interrupt); + trace_sparc64_cpu_check_irqs_noset_irq(env->tl, + cpu_tsptr(env)->tt, + new_interrupt); } else if (old_interrupt != new_interrupt) { env->interrupt_index = new_interrupt; - CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i, - old_interrupt, new_interrupt); + trace_sparc64_cpu_check_irqs_set_irq(i, old_interrupt, + new_interrupt); cpu_interrupt(cs, CPU_INTERRUPT_HARD); } break; } } } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) { - CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x " - "current interrupt %x\n", - pil, env->pil_in, env->softint, env->interrupt_index); + trace_sparc64_cpu_check_irqs_disabled(pil, env->pil_in, env->softint, + env->interrupt_index); env->interrupt_index = 0; cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } @@ -131,7 +113,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level) if (level) { if (!(env->ivec_status & 0x20)) { - CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq); + trace_sparc64_cpu_ivec_raise_irq(irq); cs = CPU(cpu); cs->halted = 0; env->interrupt_index = TT_IVEC; @@ -143,7 +125,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level) } } else { if (env->ivec_status & 0x20) { - CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq); + trace_sparc64_cpu_ivec_lower_irq(irq); cs = CPU(cpu); env->ivec_status &= ~0x20; cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); @@ -216,10 +198,10 @@ static void tick_irq(void *opaque) CPUTimer *timer = env->tick; if (timer->disabled) { - CPUIRQ_DPRINTF("tick_irq: softint disabled\n"); + trace_sparc64_cpu_tick_irq_disabled(); return; } else { - CPUIRQ_DPRINTF("tick: fire\n"); + trace_sparc64_cpu_tick_irq_fire(); } env->softint |= SOFTINT_TIMER; @@ -234,10 +216,10 @@ static void stick_irq(void *opaque) CPUTimer *timer = env->stick; if (timer->disabled) { - CPUIRQ_DPRINTF("stick_irq: softint disabled\n"); + trace_sparc64_cpu_stick_irq_disabled(); return; } else { - CPUIRQ_DPRINTF("stick: fire\n"); + trace_sparc64_cpu_stick_irq_fire(); } env->softint |= SOFTINT_STIMER; @@ -252,10 +234,10 @@ static void hstick_irq(void *opaque) CPUTimer *timer = env->hstick; if (timer->disabled) { - CPUIRQ_DPRINTF("hstick_irq: softint disabled\n"); + trace_sparc64_cpu_hstick_irq_disabled(); return; } else { - CPUIRQ_DPRINTF("hstick: fire\n"); + trace_sparc64_cpu_hstick_irq_fire(); } env->softint |= SOFTINT_STIMER; @@ -280,9 +262,9 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count) int64_t vm_clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - cpu_to_timer_ticks(real_count, timer->frequency); - TIMER_DPRINTF("%s set_count count=0x%016lx (npt %s) p=%p\n", - timer->name, real_count, - timer->npt ? "disabled" : "enabled", timer); + trace_sparc64_cpu_tick_set_count(timer->name, real_count, + timer->npt ? "disabled" : "enabled", + timer); timer->npt = npt_bit ? 1 : 0; timer->clock_offset = vm_clock_offset; @@ -294,9 +276,9 @@ uint64_t cpu_tick_get_count(CPUTimer *timer) qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->clock_offset, timer->frequency); - TIMER_DPRINTF("%s get_count count=0x%016lx (npt %s) p=%p\n", - timer->name, real_count, - timer->npt ? "disabled" : "enabled", timer); + trace_sparc64_cpu_tick_get_count(timer->name, real_count, + timer->npt ? "disabled" : "enabled", + timer); if (timer->npt) { real_count |= timer->npt_mask; @@ -319,18 +301,19 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit) expires = now + 1; } - TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p " - "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n", - timer->name, real_limit, - timer->disabled ? "disabled" : "enabled", - timer, limit, - timer_to_cpu_ticks(now - timer->clock_offset, - timer->frequency), - timer_to_cpu_ticks(expires - now, timer->frequency)); + trace_sparc64_cpu_tick_set_limit(timer->name, real_limit, + timer->disabled ? "disabled" : "enabled", + timer, limit, + timer_to_cpu_ticks( + now - timer->clock_offset, + timer->frequency + ), + timer_to_cpu_ticks( + expires - now, timer->frequency + )); if (!real_limit) { - TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n", - timer->name); + trace_sparc64_cpu_tick_set_limit_zero(timer->name); timer_del(timer->qtimer); } else if (timer->disabled) { timer_del(timer->qtimer); diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index ec45ec2801..a23cb26b0d 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -30,7 +30,7 @@ #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" #include "hw/pci/pci_host.h" -#include "hw/pci-host/apb.h" +#include "hw/pci-host/sabre.h" #include "hw/i386/pc.h" #include "hw/char/serial.h" #include "hw/timer/m48t59.h" @@ -55,9 +55,9 @@ #define CMDLINE_ADDR 0x003ff000 #define PROM_SIZE_MAX (4 * 1024 * 1024) #define PROM_VADDR 0x000ffd00000ULL -#define APB_SPECIAL_BASE 0x1fe00000000ULL -#define APB_MEM_BASE 0x1ff00000000ULL -#define APB_PCI_IO_BASE (APB_SPECIAL_BASE + 0x02000000ULL) +#define PBM_SPECIAL_BASE 0x1fe00000000ULL +#define PBM_MEM_BASE 0x1ff00000000ULL +#define PBM_PCI_IO_BASE (PBM_SPECIAL_BASE + 0x02000000ULL) #define PROM_FILENAME "openbios-sparc64" #define NVRAM_SIZE 0x2000 #define MAX_IDE_BUS 2 @@ -205,6 +205,59 @@ typedef struct ResetData { uint64_t prom_addr; } ResetData; +#define TYPE_SUN4U_POWER "power" +#define SUN4U_POWER(obj) OBJECT_CHECK(PowerDevice, (obj), TYPE_SUN4U_POWER) + +typedef struct PowerDevice { + SysBusDevice parent_obj; + + MemoryRegion power_mmio; +} PowerDevice; + +/* Power */ +static void power_mem_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + /* According to a real Ultra 5, bit 24 controls the power */ + if (val & 0x1000000) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } +} + +static const MemoryRegionOps power_mem_ops = { + .write = power_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static void power_realize(DeviceState *dev, Error **errp) +{ + PowerDevice *d = SUN4U_POWER(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&d->power_mmio, OBJECT(dev), &power_mem_ops, d, + "power", sizeof(uint32_t)); + + sysbus_init_mmio(sbd, &d->power_mmio); +} + +static void power_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = power_realize; +} + +static const TypeInfo power_info = { + .name = TYPE_SUN4U_POWER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(PowerDevice), + .class_init = power_class_init, +}; + static void ebus_isa_irq_handler(void *opaque, int n, int level) { EbusState *s = EBUS(opaque); @@ -221,6 +274,7 @@ static void ebus_isa_irq_handler(void *opaque, int n, int level) static void ebus_realize(PCIDevice *pci_dev, Error **errp) { EbusState *s = EBUS(pci_dev); + SysBusDevice *sbd; DeviceState *dev; qemu_irq *isa_irq; DriveInfo *fd[MAX_FD]; @@ -270,6 +324,13 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) qdev_prop_set_uint32(dev, "dma", -1); qdev_init_nofail(dev); + /* Power */ + dev = qdev_create(NULL, TYPE_SUN4U_POWER); + qdev_init_nofail(dev); + sbd = SYS_BUS_DEVICE(dev); + memory_region_add_subregion(pci_address_space_io(pci_dev), 0x7240, + sysbus_mmio_get_region(sbd, 0)); + /* PCI */ pci_dev->config[0x04] = 0x06; // command = bus master, pci mem pci_dev->config[0x05] = 0x00; @@ -282,7 +343,7 @@ static void ebus_realize(PCIDevice *pci_dev, Error **errp) 0, 0x1000000); pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0); memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(), - 0, 0x4000); + 0, 0x8000); pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1); } @@ -465,7 +526,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, Nvram *nvram; unsigned int i; uint64_t initrd_addr, initrd_size, kernel_addr, kernel_size, kernel_entry; - APBState *apb; + SabreState *sabre; PCIBus *pci_bus, *pci_busA, *pci_busB; PCIDevice *ebus, *pci_dev; SysBusDevice *s; @@ -488,24 +549,25 @@ static void sun4uv_init(MemoryRegion *address_space_mem, prom_init(hwdef->prom_addr, bios_name); - /* Init APB (PCI host bridge) */ - apb = APB_DEVICE(qdev_create(NULL, TYPE_APB)); - qdev_prop_set_uint64(DEVICE(apb), "special-base", APB_SPECIAL_BASE); - qdev_prop_set_uint64(DEVICE(apb), "mem-base", APB_MEM_BASE); - object_property_set_link(OBJECT(apb), OBJECT(iommu), "iommu", &error_abort); - qdev_init_nofail(DEVICE(apb)); + /* Init sabre (PCI host bridge) */ + sabre = SABRE_DEVICE(qdev_create(NULL, TYPE_SABRE)); + qdev_prop_set_uint64(DEVICE(sabre), "special-base", PBM_SPECIAL_BASE); + qdev_prop_set_uint64(DEVICE(sabre), "mem-base", PBM_MEM_BASE); + object_property_set_link(OBJECT(sabre), OBJECT(iommu), "iommu", + &error_abort); + qdev_init_nofail(DEVICE(sabre)); /* Wire up PCI interrupts to CPU */ for (i = 0; i < IVEC_MAX; i++) { - qdev_connect_gpio_out_named(DEVICE(apb), "ivec-irq", i, + qdev_connect_gpio_out_named(DEVICE(sabre), "ivec-irq", i, qdev_get_gpio_in_named(DEVICE(cpu), "ivec-irq", i)); } - pci_bus = PCI_HOST_BRIDGE(apb)->bus; - pci_busA = pci_bridge_get_sec_bus(apb->bridgeA); - pci_busB = pci_bridge_get_sec_bus(apb->bridgeB); + pci_bus = PCI_HOST_BRIDGE(sabre)->bus; + pci_busA = pci_bridge_get_sec_bus(sabre->bridgeA); + pci_busB = pci_bridge_get_sec_bus(sabre->bridgeB); - /* Only in-built Simba PBMs can exist on the root bus, slot 0 on busA is + /* Only in-built Simba APBs can exist on the root bus, slot 0 on busA is reserved (leaving no slots free after on-board devices) however slots 0-3 are free on busB */ pci_bus->slot_reserved_mask = 0xfffffffc; @@ -517,17 +579,17 @@ static void sun4uv_init(MemoryRegion *address_space_mem, hwdef->console_serial_base); qdev_init_nofail(DEVICE(ebus)); - /* Wire up "well-known" ISA IRQs to APB legacy obio IRQs */ + /* Wire up "well-known" ISA IRQs to PBM legacy obio IRQs */ qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 7, - qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_LPT_IRQ)); + qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_LPT_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 6, - qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_FDD_IRQ)); + qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_FDD_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 1, - qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_KBD_IRQ)); + qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_KBD_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 12, - qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_MSE_IRQ)); + qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_MSE_IRQ)); qdev_connect_gpio_out_named(DEVICE(ebus), "isa-irq", 4, - qdev_get_gpio_in_named(DEVICE(apb), "pbm-irq", OBIO_SER_IRQ)); + qdev_get_gpio_in_named(DEVICE(sabre), "pbm-irq", OBIO_SER_IRQ)); pci_dev = pci_create_simple(pci_busA, PCI_DEVFN(2, 0), "VGA"); @@ -693,6 +755,7 @@ static const TypeInfo sun4v_type = { static void sun4u_register_types(void) { + type_register_static(&power_info); type_register_static(&ebus_info); type_register_static(&prom_info); type_register_static(&ram_info); diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events index 2ee2d75f70..ce597a6e9d 100644 --- a/hw/sparc64/trace-events +++ b/hw/sparc64/trace-events @@ -7,3 +7,21 @@ ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d" sun4u_iommu_mem_read(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d" sun4u_iommu_mem_write(uint64_t addr, uint64_t val, int size) "addr: 0x%"PRIx64" val: 0x%"PRIx64" size: %d" sun4u_iommu_translate(uint64_t addr, uint64_t trans_addr, uint64_t tte) "xlate 0x%"PRIx64" => pa 0x%"PRIx64" tte: 0x%"PRIx64 + +# hw/sparc64/sparc64.c +sparc64_cpu_check_irqs_reset_irq(int intno) "Reset CPU IRQ (current interrupt 0x%x)" +sparc64_cpu_check_irqs_noset_irq(uint32_t tl, uint32_t tt, int intno) "Not setting CPU IRQ: TL=%d current 0x%x >= pending 0x%x" +sparc64_cpu_check_irqs_set_irq(unsigned int i, int old, int new) "Set CPU IRQ %d old=0x%x new=0x%x" +sparc64_cpu_check_irqs_disabled(uint32_t pil, uint32_t pil_in, uint32_t softint, int intno) "Interrupts disabled, pil=0x%08x pil_in=0x%08x softint=0x%08x current interrupt 0x%x" +sparc64_cpu_ivec_raise_irq(int irq) "Raise IVEC IRQ %d" +sparc64_cpu_ivec_lower_irq(int irq) "Lower IVEC IRQ %d" +sparc64_cpu_tick_irq_disabled(void) "tick_irq: softint disabled" +sparc64_cpu_tick_irq_fire(void) "tick_irq: fire" +sparc64_cpu_stick_irq_disabled(void) "stick_irq: softint disabled" +sparc64_cpu_stick_irq_fire(void) "stick_irq: fire" +sparc64_cpu_hstick_irq_disabled(void) "hstick_irq: softint disabled" +sparc64_cpu_hstick_irq_fire(void) "hstick_irq: fire" +sparc64_cpu_tick_set_count(const char *name, uint64_t real_count, const char *npt, void *p) "%s set_count count=0x%"PRIx64" (npt %s) p=%p" +sparc64_cpu_tick_get_count(const char *name, uint64_t real_count, const char *npt, void *p) "%s get_count count=0x%"PRIx64" (npt %s) p=%p" +sparc64_cpu_tick_set_limit(const char *name, uint64_t real_limit, const char *dis, void *p, uint64_t limit, uint64_t t, uint64_t dt) "%s set_limit limit=0x%"PRIx64 " (%s) p=%p called with limit=0x%"PRIx64" at 0x%"PRIx64" (delta=0x%"PRIx64")" +sparc64_cpu_tick_set_limit_zero(const char *name) "%s set_limit limit=ZERO - not starting timer" |