diff options
author | 2017-04-25 03:31:15 -0700 | |
---|---|---|
committer | 2017-05-22 06:48:08 +0000 | |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/hw/alpha | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/hw/alpha')
-rw-r--r-- | qemu/hw/alpha/Makefile.objs | 1 | ||||
-rw-r--r-- | qemu/hw/alpha/alpha_sys.h | 21 | ||||
-rw-r--r-- | qemu/hw/alpha/dp264.c | 184 | ||||
-rw-r--r-- | qemu/hw/alpha/pci.c | 94 | ||||
-rw-r--r-- | qemu/hw/alpha/typhoon.c | 959 |
5 files changed, 0 insertions, 1259 deletions
diff --git a/qemu/hw/alpha/Makefile.objs b/qemu/hw/alpha/Makefile.objs deleted file mode 100644 index 5c742756f..000000000 --- a/qemu/hw/alpha/Makefile.objs +++ /dev/null @@ -1 +0,0 @@ -obj-y += dp264.o pci.o typhoon.o diff --git a/qemu/hw/alpha/alpha_sys.h b/qemu/hw/alpha/alpha_sys.h deleted file mode 100644 index e11025b4b..000000000 --- a/qemu/hw/alpha/alpha_sys.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Alpha cores and system support chips. */ - -#ifndef HW_ALPHA_H -#define HW_ALPHA_H 1 - -#include "hw/pci/pci.h" -#include "hw/pci/pci_host.h" -#include "hw/ide.h" -#include "hw/i386/pc.h" -#include "hw/irq.h" - - -PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4], - pci_map_irq_fn); - -/* alpha_pci.c. */ -extern const MemoryRegionOps alpha_pci_ignore_ops; -extern const MemoryRegionOps alpha_pci_conf1_ops; -extern const MemoryRegionOps alpha_pci_iack_ops; - -#endif diff --git a/qemu/hw/alpha/dp264.c b/qemu/hw/alpha/dp264.c deleted file mode 100644 index f1267b544..000000000 --- a/qemu/hw/alpha/dp264.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * QEMU Alpha DP264/CLIPPER hardware system emulator. - * - * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK - * variants because CLIPPER doesn't have an SMC669 SuperIO controller - * that we need to emulate as well. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "cpu.h" -#include "hw/hw.h" -#include "elf.h" -#include "hw/loader.h" -#include "hw/boards.h" -#include "alpha_sys.h" -#include "qemu/error-report.h" -#include "sysemu/sysemu.h" -#include "hw/timer/mc146818rtc.h" -#include "hw/ide.h" -#include "hw/timer/i8254.h" -#include "hw/char/serial.h" -#include "qemu/cutils.h" - -#define MAX_IDE_BUS 2 - -static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) -{ - if (((addr >> 41) & 3) == 2) { - addr &= 0xffffffffffull; - } - return addr; -} - -/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems. - (0) The dev_irq_n lines into the cpu, which we totally ignore, - (1) The DRIR lines in the typhoon chipset, - (2) The "vector" aka mangled interrupt number reported by SRM PALcode, - (3) The interrupt number assigned by the kernel. - The following function is concerned with (1) only. */ - -static int clipper_pci_map_irq(PCIDevice *d, int irq_num) -{ - int slot = d->devfn >> 3; - - assert(irq_num >= 0 && irq_num <= 3); - - return (slot + 1) * 4 + irq_num; -} - -static void clipper_init(MachineState *machine) -{ - ram_addr_t ram_size = machine->ram_size; - const char *cpu_model = machine->cpu_model; - const char *kernel_filename = machine->kernel_filename; - const char *kernel_cmdline = machine->kernel_cmdline; - const char *initrd_filename = machine->initrd_filename; - AlphaCPU *cpus[4]; - PCIBus *pci_bus; - ISABus *isa_bus; - qemu_irq rtc_irq; - long size, i; - char *palcode_filename; - uint64_t palcode_entry, palcode_low, palcode_high; - uint64_t kernel_entry, kernel_low, kernel_high; - - /* Create up to 4 cpus. */ - memset(cpus, 0, sizeof(cpus)); - for (i = 0; i < smp_cpus; ++i) { - cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67"); - } - - cpus[0]->env.trap_arg0 = ram_size; - cpus[0]->env.trap_arg1 = 0; - cpus[0]->env.trap_arg2 = smp_cpus; - - /* Init the chipset. */ - pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, - clipper_pci_map_irq); - - /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ - rtc_init(isa_bus, 1900, rtc_irq); - - pit_init(isa_bus, 0x40, 0, NULL); - isa_create_simple(isa_bus, "i8042"); - - /* VGA setup. Don't bother loading the bios. */ - pci_vga_init(pci_bus); - - /* Serial code setup. */ - serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS); - - /* Network setup. e1000 is good enough, failing Tulip support. */ - for (i = 0; i < nb_nics; i++) { - pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL); - } - - /* IDE disk setup. */ - { - DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - ide_drive_get(hd, ARRAY_SIZE(hd)); - - pci_cmd646_ide_init(pci_bus, hd, 0); - } - - /* Load PALcode. Given that this is not "real" cpu palcode, - but one explicitly written for the emulation, we might as - well load it directly from and ELF image. */ - palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, - bios_name ? bios_name : "palcode-clipper"); - if (palcode_filename == NULL) { - error_report("no palcode provided"); - exit(1); - } - size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, - NULL, &palcode_entry, &palcode_low, &palcode_high, - 0, EM_ALPHA, 0, 0); - if (size < 0) { - error_report("could not load palcode '%s'", palcode_filename); - exit(1); - } - g_free(palcode_filename); - - /* Start all cpus at the PALcode RESET entry point. */ - for (i = 0; i < smp_cpus; ++i) { - cpus[i]->env.pal_mode = 1; - cpus[i]->env.pc = palcode_entry; - cpus[i]->env.palbr = palcode_entry; - } - - /* Load a kernel. */ - if (kernel_filename) { - uint64_t param_offset; - - size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, - NULL, &kernel_entry, &kernel_low, &kernel_high, - 0, EM_ALPHA, 0, 0); - if (size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - - cpus[0]->env.trap_arg1 = kernel_entry; - - param_offset = kernel_low - 0x6000; - - if (kernel_cmdline) { - pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); - } - - if (initrd_filename) { - long initrd_base, initrd_size; - - initrd_size = get_image_size(initrd_filename); - if (initrd_size < 0) { - error_report("could not load initial ram disk '%s'", - initrd_filename); - exit(1); - } - - /* Put the initrd image as high in memory as possible. */ - initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; - load_image_targphys(initrd_filename, initrd_base, - ram_size - initrd_base); - - address_space_stq(&address_space_memory, param_offset + 0x100, - initrd_base + 0xfffffc0000000000ULL, - MEMTXATTRS_UNSPECIFIED, - NULL); - address_space_stq(&address_space_memory, param_offset + 0x108, - initrd_size, MEMTXATTRS_UNSPECIFIED, NULL); - } - } -} - -static void clipper_machine_init(MachineClass *mc) -{ - mc->desc = "Alpha DP264/CLIPPER"; - mc->init = clipper_init; - mc->max_cpus = 4; - mc->is_default = 1; -} - -DEFINE_MACHINE("clipper", clipper_machine_init) diff --git a/qemu/hw/alpha/pci.c b/qemu/hw/alpha/pci.c deleted file mode 100644 index 5baa0eaf1..000000000 --- a/qemu/hw/alpha/pci.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * QEMU Alpha PCI support functions. - * - * Some of this isn't very Alpha specific at all. - * - * ??? Sparse memory access not implemented. - */ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "cpu.h" -#include "alpha_sys.h" -#include "qemu/log.h" -#include "sysemu/sysemu.h" -#include "trace.h" - - -/* Fallback for unassigned PCI I/O operations. Avoids MCHK. */ - -static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size) -{ - return 0; -} - -static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size) -{ -} - -const MemoryRegionOps alpha_pci_ignore_ops = { - .read = ignore_read, - .write = ignore_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 1, - .max_access_size = 8, - }, -}; - - -/* PCI config space reads/writes, to byte-word addressable memory. */ -static uint64_t bw_conf1_read(void *opaque, hwaddr addr, - unsigned size) -{ - PCIBus *b = opaque; - return pci_data_read(b, addr, size); -} - -static void bw_conf1_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PCIBus *b = opaque; - pci_data_write(b, addr, val, size); -} - -const MemoryRegionOps alpha_pci_conf1_ops = { - .read = bw_conf1_read, - .write = bw_conf1_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .impl = { - .min_access_size = 1, - .max_access_size = 4, - }, -}; - -/* PCI/EISA Interrupt Acknowledge Cycle. */ - -static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size) -{ - return pic_read_irq(isa_pic); -} - -static void special_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - trace_alpha_pci_iack_write(); -} - -const MemoryRegionOps alpha_pci_iack_ops = { - .read = iack_read, - .write = special_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4, - }, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, -}; diff --git a/qemu/hw/alpha/typhoon.c b/qemu/hw/alpha/typhoon.c deleted file mode 100644 index 97721b535..000000000 --- a/qemu/hw/alpha/typhoon.c +++ /dev/null @@ -1,959 +0,0 @@ -/* - * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation. - * - * Written by Richard Henderson. - * - * This work is licensed under the GNU GPL license version 2 or later. - */ - -#include "qemu/osdep.h" -#include "qapi/error.h" -#include "cpu.h" -#include "hw/hw.h" -#include "hw/devices.h" -#include "sysemu/sysemu.h" -#include "alpha_sys.h" -#include "exec/address-spaces.h" - - -#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" - -typedef struct TyphoonCchip { - MemoryRegion region; - uint64_t misc; - uint64_t drir; - uint64_t dim[4]; - uint32_t iic[4]; - AlphaCPU *cpu[4]; -} TyphoonCchip; - -typedef struct TyphoonWindow { - uint64_t wba; - uint64_t wsm; - uint64_t tba; -} TyphoonWindow; - -typedef struct TyphoonPchip { - MemoryRegion region; - MemoryRegion reg_iack; - MemoryRegion reg_mem; - MemoryRegion reg_io; - MemoryRegion reg_conf; - - AddressSpace iommu_as; - MemoryRegion iommu; - - uint64_t ctl; - TyphoonWindow win[4]; -} TyphoonPchip; - -#define TYPHOON_PCI_HOST_BRIDGE(obj) \ - OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE) - -typedef struct TyphoonState { - PCIHostState parent_obj; - - TyphoonCchip cchip; - TyphoonPchip pchip; - MemoryRegion dchip_region; - MemoryRegion ram_region; -} TyphoonState; - -/* Called when one of DRIR or DIM changes. */ -static void cpu_irq_change(AlphaCPU *cpu, uint64_t req) -{ - /* If there are any non-masked interrupts, tell the cpu. */ - if (cpu != NULL) { - CPUState *cs = CPU(cpu); - if (req) { - cpu_interrupt(cs, CPU_INTERRUPT_HARD); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - } - } -} - -static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) -{ - CPUState *cpu = current_cpu; - TyphoonState *s = opaque; - uint64_t ret = 0; - - switch (addr) { - case 0x0000: - /* CSC: Cchip System Configuration Register. */ - /* All sorts of data here; probably the only thing relevant is - PIP<14> Pchip 1 Present = 0. */ - break; - - case 0x0040: - /* MTR: Memory Timing Register. */ - /* All sorts of stuff related to real DRAM. */ - break; - - case 0x0080: - /* MISC: Miscellaneous Register. */ - ret = s->cchip.misc | (cpu->cpu_index & 3); - break; - - case 0x00c0: - /* MPD: Memory Presence Detect Register. */ - break; - - case 0x0100: /* AAR0 */ - case 0x0140: /* AAR1 */ - case 0x0180: /* AAR2 */ - case 0x01c0: /* AAR3 */ - /* AAR: Array Address Register. */ - /* All sorts of information about DRAM. */ - break; - - case 0x0200: - /* DIM0: Device Interrupt Mask Register, CPU0. */ - ret = s->cchip.dim[0]; - break; - case 0x0240: - /* DIM1: Device Interrupt Mask Register, CPU1. */ - ret = s->cchip.dim[1]; - break; - case 0x0280: - /* DIR0: Device Interrupt Request Register, CPU0. */ - ret = s->cchip.dim[0] & s->cchip.drir; - break; - case 0x02c0: - /* DIR1: Device Interrupt Request Register, CPU1. */ - ret = s->cchip.dim[1] & s->cchip.drir; - break; - case 0x0300: - /* DRIR: Device Raw Interrupt Request Register. */ - ret = s->cchip.drir; - break; - - case 0x0340: - /* PRBEN: Probe Enable Register. */ - break; - - case 0x0380: - /* IIC0: Interval Ignore Count Register, CPU0. */ - ret = s->cchip.iic[0]; - break; - case 0x03c0: - /* IIC1: Interval Ignore Count Register, CPU1. */ - ret = s->cchip.iic[1]; - break; - - case 0x0400: /* MPR0 */ - case 0x0440: /* MPR1 */ - case 0x0480: /* MPR2 */ - case 0x04c0: /* MPR3 */ - /* MPR: Memory Programming Register. */ - break; - - case 0x0580: - /* TTR: TIGbus Timing Register. */ - /* All sorts of stuff related to interrupt delivery timings. */ - break; - case 0x05c0: - /* TDR: TIGbug Device Timing Register. */ - break; - - case 0x0600: - /* DIM2: Device Interrupt Mask Register, CPU2. */ - ret = s->cchip.dim[2]; - break; - case 0x0640: - /* DIM3: Device Interrupt Mask Register, CPU3. */ - ret = s->cchip.dim[3]; - break; - case 0x0680: - /* DIR2: Device Interrupt Request Register, CPU2. */ - ret = s->cchip.dim[2] & s->cchip.drir; - break; - case 0x06c0: - /* DIR3: Device Interrupt Request Register, CPU3. */ - ret = s->cchip.dim[3] & s->cchip.drir; - break; - - case 0x0700: - /* IIC2: Interval Ignore Count Register, CPU2. */ - ret = s->cchip.iic[2]; - break; - case 0x0740: - /* IIC3: Interval Ignore Count Register, CPU3. */ - ret = s->cchip.iic[3]; - break; - - case 0x0780: - /* PWR: Power Management Control. */ - break; - - case 0x0c00: /* CMONCTLA */ - case 0x0c40: /* CMONCTLB */ - case 0x0c80: /* CMONCNT01 */ - case 0x0cc0: /* CMONCNT23 */ - break; - - default: - cpu_unassigned_access(cpu, addr, false, false, 0, size); - return -1; - } - - return ret; -} - -static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size) -{ - /* Skip this. It's all related to DRAM timing and setup. */ - return 0; -} - -static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) -{ - TyphoonState *s = opaque; - uint64_t ret = 0; - - switch (addr) { - case 0x0000: - /* WSBA0: Window Space Base Address Register. */ - ret = s->pchip.win[0].wba; - break; - case 0x0040: - /* WSBA1 */ - ret = s->pchip.win[1].wba; - break; - case 0x0080: - /* WSBA2 */ - ret = s->pchip.win[2].wba; - break; - case 0x00c0: - /* WSBA3 */ - ret = s->pchip.win[3].wba; - break; - - case 0x0100: - /* WSM0: Window Space Mask Register. */ - ret = s->pchip.win[0].wsm; - break; - case 0x0140: - /* WSM1 */ - ret = s->pchip.win[1].wsm; - break; - case 0x0180: - /* WSM2 */ - ret = s->pchip.win[2].wsm; - break; - case 0x01c0: - /* WSM3 */ - ret = s->pchip.win[3].wsm; - break; - - case 0x0200: - /* TBA0: Translated Base Address Register. */ - ret = s->pchip.win[0].tba; - break; - case 0x0240: - /* TBA1 */ - ret = s->pchip.win[1].tba; - break; - case 0x0280: - /* TBA2 */ - ret = s->pchip.win[2].tba; - break; - case 0x02c0: - /* TBA3 */ - ret = s->pchip.win[3].tba; - break; - - case 0x0300: - /* PCTL: Pchip Control Register. */ - ret = s->pchip.ctl; - break; - case 0x0340: - /* PLAT: Pchip Master Latency Register. */ - break; - case 0x03c0: - /* PERROR: Pchip Error Register. */ - break; - case 0x0400: - /* PERRMASK: Pchip Error Mask Register. */ - break; - case 0x0440: - /* PERRSET: Pchip Error Set Register. */ - break; - case 0x0480: - /* TLBIV: Translation Buffer Invalidate Virtual Register (WO). */ - break; - case 0x04c0: - /* TLBIA: Translation Buffer Invalidate All Register (WO). */ - break; - case 0x0500: /* PMONCTL */ - case 0x0540: /* PMONCNT */ - case 0x0800: /* SPRST */ - break; - - default: - cpu_unassigned_access(current_cpu, addr, false, false, 0, size); - return -1; - } - - return ret; -} - -static void cchip_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TyphoonState *s = opaque; - uint64_t oldval, newval; - - switch (addr) { - case 0x0000: - /* CSC: Cchip System Configuration Register. */ - /* All sorts of data here; nothing relevant RW. */ - break; - - case 0x0040: - /* MTR: Memory Timing Register. */ - /* All sorts of stuff related to real DRAM. */ - break; - - case 0x0080: - /* MISC: Miscellaneous Register. */ - newval = oldval = s->cchip.misc; - newval &= ~(val & 0x10000ff0); /* W1C fields */ - if (val & 0x100000) { - newval &= ~0xff0000ull; /* ACL clears ABT and ABW */ - } else { - newval |= val & 0x00f00000; /* ABT field is W1S */ - if ((newval & 0xf0000) == 0) { - newval |= val & 0xf0000; /* ABW field is W1S iff zero */ - } - } - newval |= (val & 0xf000) >> 4; /* IPREQ field sets IPINTR. */ - - newval &= ~0xf0000000000ull; /* WO and RW fields */ - newval |= val & 0xf0000000000ull; - s->cchip.misc = newval; - - /* Pass on changes to IPI and ITI state. */ - if ((newval ^ oldval) & 0xff0) { - int i; - for (i = 0; i < 4; ++i) { - AlphaCPU *cpu = s->cchip.cpu[i]; - if (cpu != NULL) { - CPUState *cs = CPU(cpu); - /* IPI can be either cleared or set by the write. */ - if (newval & (1 << (i + 8))) { - cpu_interrupt(cs, CPU_INTERRUPT_SMP); - } else { - cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP); - } - - /* ITI can only be cleared by the write. */ - if ((newval & (1 << (i + 4))) == 0) { - cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER); - } - } - } - } - break; - - case 0x00c0: - /* MPD: Memory Presence Detect Register. */ - break; - - case 0x0100: /* AAR0 */ - case 0x0140: /* AAR1 */ - case 0x0180: /* AAR2 */ - case 0x01c0: /* AAR3 */ - /* AAR: Array Address Register. */ - /* All sorts of information about DRAM. */ - break; - - case 0x0200: /* DIM0 */ - /* DIM: Device Interrupt Mask Register, CPU0. */ - s->cchip.dim[0] = val; - cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir); - break; - case 0x0240: /* DIM1 */ - /* DIM: Device Interrupt Mask Register, CPU1. */ - s->cchip.dim[0] = val; - cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir); - break; - - case 0x0280: /* DIR0 (RO) */ - case 0x02c0: /* DIR1 (RO) */ - case 0x0300: /* DRIR (RO) */ - break; - - case 0x0340: - /* PRBEN: Probe Enable Register. */ - break; - - case 0x0380: /* IIC0 */ - s->cchip.iic[0] = val & 0xffffff; - break; - case 0x03c0: /* IIC1 */ - s->cchip.iic[1] = val & 0xffffff; - break; - - case 0x0400: /* MPR0 */ - case 0x0440: /* MPR1 */ - case 0x0480: /* MPR2 */ - case 0x04c0: /* MPR3 */ - /* MPR: Memory Programming Register. */ - break; - - case 0x0580: - /* TTR: TIGbus Timing Register. */ - /* All sorts of stuff related to interrupt delivery timings. */ - break; - case 0x05c0: - /* TDR: TIGbug Device Timing Register. */ - break; - - case 0x0600: - /* DIM2: Device Interrupt Mask Register, CPU2. */ - s->cchip.dim[2] = val; - cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir); - break; - case 0x0640: - /* DIM3: Device Interrupt Mask Register, CPU3. */ - s->cchip.dim[3] = val; - cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir); - break; - - case 0x0680: /* DIR2 (RO) */ - case 0x06c0: /* DIR3 (RO) */ - break; - - case 0x0700: /* IIC2 */ - s->cchip.iic[2] = val & 0xffffff; - break; - case 0x0740: /* IIC3 */ - s->cchip.iic[3] = val & 0xffffff; - break; - - case 0x0780: - /* PWR: Power Management Control. */ - break; - - case 0x0c00: /* CMONCTLA */ - case 0x0c40: /* CMONCTLB */ - case 0x0c80: /* CMONCNT01 */ - case 0x0cc0: /* CMONCNT23 */ - break; - - default: - cpu_unassigned_access(current_cpu, addr, true, false, 0, size); - return; - } -} - -static void dchip_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - /* Skip this. It's all related to DRAM timing and setup. */ -} - -static void pchip_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - TyphoonState *s = opaque; - uint64_t oldval; - - switch (addr) { - case 0x0000: - /* WSBA0: Window Space Base Address Register. */ - s->pchip.win[0].wba = val & 0xfff00003u; - break; - case 0x0040: - /* WSBA1 */ - s->pchip.win[1].wba = val & 0xfff00003u; - break; - case 0x0080: - /* WSBA2 */ - s->pchip.win[2].wba = val & 0xfff00003u; - break; - case 0x00c0: - /* WSBA3 */ - s->pchip.win[3].wba = (val & 0x80fff00001ull) | 2; - break; - - case 0x0100: - /* WSM0: Window Space Mask Register. */ - s->pchip.win[0].wsm = val & 0xfff00000u; - break; - case 0x0140: - /* WSM1 */ - s->pchip.win[1].wsm = val & 0xfff00000u; - break; - case 0x0180: - /* WSM2 */ - s->pchip.win[2].wsm = val & 0xfff00000u; - break; - case 0x01c0: - /* WSM3 */ - s->pchip.win[3].wsm = val & 0xfff00000u; - break; - - case 0x0200: - /* TBA0: Translated Base Address Register. */ - s->pchip.win[0].tba = val & 0x7fffffc00ull; - break; - case 0x0240: - /* TBA1 */ - s->pchip.win[1].tba = val & 0x7fffffc00ull; - break; - case 0x0280: - /* TBA2 */ - s->pchip.win[2].tba = val & 0x7fffffc00ull; - break; - case 0x02c0: - /* TBA3 */ - s->pchip.win[3].tba = val & 0x7fffffc00ull; - break; - - case 0x0300: - /* PCTL: Pchip Control Register. */ - oldval = s->pchip.ctl; - oldval &= ~0x00001cff0fc7ffull; /* RW fields */ - oldval |= val & 0x00001cff0fc7ffull; - s->pchip.ctl = oldval; - break; - - case 0x0340: - /* PLAT: Pchip Master Latency Register. */ - break; - case 0x03c0: - /* PERROR: Pchip Error Register. */ - break; - case 0x0400: - /* PERRMASK: Pchip Error Mask Register. */ - break; - case 0x0440: - /* PERRSET: Pchip Error Set Register. */ - break; - - case 0x0480: - /* TLBIV: Translation Buffer Invalidate Virtual Register. */ - break; - - case 0x04c0: - /* TLBIA: Translation Buffer Invalidate All Register (WO). */ - break; - - case 0x0500: - /* PMONCTL */ - case 0x0540: - /* PMONCNT */ - case 0x0800: - /* SPRST */ - break; - - default: - cpu_unassigned_access(current_cpu, addr, true, false, 0, size); - return; - } -} - -static const MemoryRegionOps cchip_ops = { - .read = cchip_read, - .write = cchip_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 8, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 8, - .max_access_size = 8, - }, -}; - -static const MemoryRegionOps dchip_ops = { - .read = dchip_read, - .write = dchip_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 8, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 8, - .max_access_size = 8, - }, -}; - -static const MemoryRegionOps pchip_ops = { - .read = pchip_read, - .write = pchip_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 8, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 8, - .max_access_size = 8, - }, -}; - -/* A subroutine of typhoon_translate_iommu that builds an IOMMUTLBEntry - using the given translated address and mask. */ -static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret) -{ - *ret = (IOMMUTLBEntry) { - .target_as = &address_space_memory, - .translated_addr = taddr, - .addr_mask = mask, - .perm = IOMMU_RW, - }; - return true; -} - -/* A subroutine of typhoon_translate_iommu that handles scatter-gather - translation, given the address of the PTE. */ -static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret) -{ - uint64_t pte = address_space_ldq(&address_space_memory, pte_addr, - MEMTXATTRS_UNSPECIFIED, NULL); - - /* Check valid bit. */ - if ((pte & 1) == 0) { - return false; - } - - return make_iommu_tlbe((pte & 0x3ffffe) << 12, 0x1fff, ret); -} - -/* A subroutine of typhoon_translate_iommu that handles one of the - four single-address-cycle translation windows. */ -static bool window_translate(TyphoonWindow *win, hwaddr addr, - IOMMUTLBEntry *ret) -{ - uint32_t wba = win->wba; - uint64_t wsm = win->wsm; - uint64_t tba = win->tba; - uint64_t wsm_ext = wsm | 0xfffff; - - /* Check for window disabled. */ - if ((wba & 1) == 0) { - return false; - } - - /* Check for window hit. */ - if ((addr & ~wsm_ext) != (wba & 0xfff00000u)) { - return false; - } - - if (wba & 2) { - /* Scatter-gather translation. */ - hwaddr pte_addr; - - /* See table 10-6, Generating PTE address for PCI DMA Address. */ - pte_addr = tba & ~(wsm >> 10); - pte_addr |= (addr & (wsm | 0xfe000)) >> 10; - return pte_translate(pte_addr, ret); - } else { - /* Direct-mapped translation. */ - return make_iommu_tlbe(tba & ~wsm_ext, wsm_ext, ret); - } -} - -/* Handle PCI-to-system address translation. */ -/* TODO: A translation failure here ought to set PCI error codes on the - Pchip and generate a machine check interrupt. */ -static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr, - bool is_write) -{ - TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu); - IOMMUTLBEntry ret; - int i; - - if (addr <= 0xffffffffu) { - /* Single-address cycle. */ - - /* Check for the Window Hole, inhibiting matching. */ - if ((pchip->ctl & 0x20) - && addr >= 0x80000 - && addr <= 0xfffff) { - goto failure; - } - - /* Check the first three windows. */ - for (i = 0; i < 3; ++i) { - if (window_translate(&pchip->win[i], addr, &ret)) { - goto success; - } - } - - /* Check the fourth window for DAC disable. */ - if ((pchip->win[3].wba & 0x80000000000ull) == 0 - && window_translate(&pchip->win[3], addr, &ret)) { - goto success; - } - } else { - /* Double-address cycle. */ - - if (addr >= 0x10000000000ull && addr < 0x20000000000ull) { - /* Check for the DMA monster window. */ - if (pchip->ctl & 0x40) { - /* See 10.1.4.4; in particular <39:35> is ignored. */ - make_iommu_tlbe(0, 0x007ffffffffull, &ret); - goto success; - } - } - - if (addr >= 0x80000000000ull && addr <= 0xfffffffffffull) { - /* Check the fourth window for DAC enable and window enable. */ - if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) { - uint64_t pte_addr; - - pte_addr = pchip->win[3].tba & 0x7ffc00000ull; - pte_addr |= (addr & 0xffffe000u) >> 10; - if (pte_translate(pte_addr, &ret)) { - goto success; - } - } - } - } - - failure: - ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE }; - success: - return ret; -} - -static const MemoryRegionIOMMUOps typhoon_iommu_ops = { - .translate = typhoon_translate_iommu, -}; - -static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) -{ - TyphoonState *s = opaque; - return &s->pchip.iommu_as; -} - -static void typhoon_set_irq(void *opaque, int irq, int level) -{ - TyphoonState *s = opaque; - uint64_t drir; - int i; - - /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL. */ - drir = s->cchip.drir; - if (level) { - drir |= 1ull << irq; - } else { - drir &= ~(1ull << irq); - } - s->cchip.drir = drir; - - for (i = 0; i < 4; ++i) { - cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir); - } -} - -static void typhoon_set_isa_irq(void *opaque, int irq, int level) -{ - typhoon_set_irq(opaque, 55, level); -} - -static void typhoon_set_timer_irq(void *opaque, int irq, int level) -{ - TyphoonState *s = opaque; - int i; - - /* Thankfully, the mc146818rtc code doesn't track the IRQ state, - and so we don't have to worry about missing interrupts just - because we never actually ACK the interrupt. Just ignore any - case of the interrupt level going low. */ - if (level == 0) { - return; - } - - /* Deliver the interrupt to each CPU, considering each CPU's IIC. */ - for (i = 0; i < 4; ++i) { - AlphaCPU *cpu = s->cchip.cpu[i]; - if (cpu != NULL) { - uint32_t iic = s->cchip.iic[i]; - - /* ??? The verbage in Section 10.2.2.10 isn't 100% clear. - Bit 24 is the OverFlow bit, RO, and set when the count - decrements past 0. When is OF cleared? My guess is that - OF is actually cleared when the IIC is written, and that - the ICNT field always decrements. At least, that's an - interpretation that makes sense, and "allows the CPU to - determine exactly how mant interval timer ticks were - skipped". At least within the next 4M ticks... */ - - iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000); - s->cchip.iic[i] = iic; - - if (iic & 0x1000000) { - /* Set the ITI bit for this cpu. */ - s->cchip.misc |= 1 << (i + 4); - /* And signal the interrupt. */ - cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER); - } - } - } -} - -static void typhoon_alarm_timer(void *opaque) -{ - TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3); - int cpu = (uintptr_t)opaque & 3; - - /* Set the ITI bit for this cpu. */ - s->cchip.misc |= 1 << (cpu + 4); - cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER); -} - -PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, - qemu_irq *p_rtc_irq, - AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq) -{ - const uint64_t MB = 1024 * 1024; - const uint64_t GB = 1024 * MB; - MemoryRegion *addr_space = get_system_memory(); - DeviceState *dev; - TyphoonState *s; - PCIHostState *phb; - PCIBus *b; - int i; - - dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE); - qdev_init_nofail(dev); - - s = TYPHOON_PCI_HOST_BRIDGE(dev); - phb = PCI_HOST_BRIDGE(dev); - - s->cchip.misc = 0x800000000ull; /* Revision: Typhoon. */ - s->pchip.win[3].wba = 2; /* Window 3 SG always enabled. */ - - /* Remember the CPUs so that we can deliver interrupts to them. */ - for (i = 0; i < 4; i++) { - AlphaCPU *cpu = cpus[i]; - s->cchip.cpu[i] = cpu; - if (cpu != NULL) { - cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, - typhoon_alarm_timer, - (void *)((uintptr_t)s + i)); - } - } - - *p_rtc_irq = qemu_allocate_irq(typhoon_set_timer_irq, s, 0); - - /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB, - but the address space hole reserved at this point is 8TB. */ - memory_region_allocate_system_memory(&s->ram_region, OBJECT(s), "ram", - ram_size); - memory_region_add_subregion(addr_space, 0, &s->ram_region); - - /* TIGbus, 0x801.0000.0000, 1GB. */ - /* ??? The TIGbus is used for delivering interrupts, and access to - the flash ROM. I'm not sure that we need to implement it at all. */ - - /* Pchip0 CSRs, 0x801.8000.0000, 256MB. */ - memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0", - 256*MB); - memory_region_add_subregion(addr_space, 0x80180000000ULL, - &s->pchip.region); - - /* Cchip CSRs, 0x801.A000.0000, 256MB. */ - memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0", - 256*MB); - memory_region_add_subregion(addr_space, 0x801a0000000ULL, - &s->cchip.region); - - /* Dchip CSRs, 0x801.B000.0000, 256MB. */ - memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0", - 256*MB); - memory_region_add_subregion(addr_space, 0x801b0000000ULL, - &s->dchip_region); - - /* Pchip0 PCI memory, 0x800.0000.0000, 4GB. */ - memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4*GB); - memory_region_add_subregion(addr_space, 0x80000000000ULL, - &s->pchip.reg_mem); - - /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB. */ - memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops, - NULL, "pci0-io", 32*MB); - memory_region_add_subregion(addr_space, 0x801fc000000ULL, - &s->pchip.reg_io); - - b = pci_register_bus(dev, "pci", - typhoon_set_irq, sys_map_irq, s, - &s->pchip.reg_mem, &s->pchip.reg_io, - 0, 64, TYPE_PCI_BUS); - phb->bus = b; - - /* Host memory as seen from the PCI side, via the IOMMU. */ - memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops, - "iommu-typhoon", UINT64_MAX); - address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci"); - pci_setup_iommu(b, typhoon_pci_dma_iommu, s); - - /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */ - memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops, - b, "pci0-iack", 64*MB); - memory_region_add_subregion(addr_space, 0x801f8000000ULL, - &s->pchip.reg_iack); - - /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB. */ - memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops, - b, "pci0-conf", 16*MB); - memory_region_add_subregion(addr_space, 0x801fe000000ULL, - &s->pchip.reg_conf); - - /* For the record, these are the mappings for the second PCI bus. - We can get away with not implementing them because we indicate - via the Cchip.CSC<PIP> bit that Pchip1 is not present. */ - /* Pchip1 PCI memory, 0x802.0000.0000, 4GB. */ - /* Pchip1 CSRs, 0x802.8000.0000, 256MB. */ - /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB. */ - /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB. */ - /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB. */ - - /* Init the ISA bus. */ - /* ??? Technically there should be a cy82c693ub pci-isa bridge. */ - { - qemu_irq *isa_irqs; - - *isa_bus = isa_bus_new(NULL, get_system_memory(), &s->pchip.reg_io, - &error_abort); - isa_irqs = i8259_init(*isa_bus, - qemu_allocate_irq(typhoon_set_isa_irq, s, 0)); - isa_bus_irqs(*isa_bus, isa_irqs); - } - - return b; -} - -static int typhoon_pcihost_init(SysBusDevice *dev) -{ - return 0; -} - -static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = typhoon_pcihost_init; -} - -static const TypeInfo typhoon_pcihost_info = { - .name = TYPE_TYPHOON_PCI_HOST_BRIDGE, - .parent = TYPE_PCI_HOST_BRIDGE, - .instance_size = sizeof(TyphoonState), - .class_init = typhoon_pcihost_class_init, -}; - -static void typhoon_register_types(void) -{ - type_register_static(&typhoon_pcihost_info); -} - -type_init(typhoon_register_types) |