diff options
Diffstat (limited to 'qemu/hw/ppc/ppce500_spin.c')
-rw-r--r-- | qemu/hw/ppc/ppce500_spin.c | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/qemu/hw/ppc/ppce500_spin.c b/qemu/hw/ppc/ppce500_spin.c deleted file mode 100644 index 76bd78bfd..000000000 --- a/qemu/hw/ppc/ppce500_spin.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * QEMU PowerPC e500v2 ePAPR spinning code - * - * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Alexander Graf, <agraf@suse.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - * This code is not really a device, but models an interface that usually - * firmware takes care of. It's used when QEMU plays the role of firmware. - * - * Specification: - * - * https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.1.pdf - * - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "sysemu/sysemu.h" -#include "hw/sysbus.h" -#include "sysemu/kvm.h" - -#define MAX_CPUS 32 - -typedef struct spin_info { - uint64_t addr; - uint64_t r3; - uint32_t resv; - uint32_t pir; - uint64_t reserved; -} QEMU_PACKED SpinInfo; - -#define TYPE_E500_SPIN "e500-spin" -#define E500_SPIN(obj) OBJECT_CHECK(SpinState, (obj), TYPE_E500_SPIN) - -typedef struct SpinState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - SpinInfo spin[MAX_CPUS]; -} SpinState; - -typedef struct spin_kick { - PowerPCCPU *cpu; - SpinInfo *spin; -} SpinKick; - -static void spin_reset(void *opaque) -{ - SpinState *s = opaque; - int i; - - for (i = 0; i < MAX_CPUS; i++) { - SpinInfo *info = &s->spin[i]; - - stl_p(&info->pir, i); - stq_p(&info->r3, i); - stq_p(&info->addr, 1); - } -} - -/* Create -kernel TLB entries for BookE, linearly spanning 256MB. */ -static inline hwaddr booke206_page_size_to_tlb(uint64_t size) -{ - return ctz32(size >> 10) >> 1; -} - -static void mmubooke_create_initial_mapping(CPUPPCState *env, - target_ulong va, - hwaddr pa, - hwaddr len) -{ - ppcmas_tlb_t *tlb = booke206_get_tlbm(env, 1, 0, 1); - hwaddr size; - - size = (booke206_page_size_to_tlb(len) << MAS1_TSIZE_SHIFT); - tlb->mas1 = MAS1_VALID | size; - tlb->mas2 = (va & TARGET_PAGE_MASK) | MAS2_M; - tlb->mas7_3 = pa & TARGET_PAGE_MASK; - tlb->mas7_3 |= MAS3_UR | MAS3_UW | MAS3_UX | MAS3_SR | MAS3_SW | MAS3_SX; - env->tlb_dirty = true; -} - -static void spin_kick(void *data) -{ - SpinKick *kick = data; - CPUState *cpu = CPU(kick->cpu); - CPUPPCState *env = &kick->cpu->env; - SpinInfo *curspin = kick->spin; - hwaddr map_size = 64 * 1024 * 1024; - hwaddr map_start; - - cpu_synchronize_state(cpu); - stl_p(&curspin->pir, env->spr[SPR_PIR]); - env->nip = ldq_p(&curspin->addr) & (map_size - 1); - env->gpr[3] = ldq_p(&curspin->r3); - env->gpr[4] = 0; - env->gpr[5] = 0; - env->gpr[6] = 0; - env->gpr[7] = map_size; - env->gpr[8] = 0; - env->gpr[9] = 0; - - map_start = ldq_p(&curspin->addr) & ~(map_size - 1); - mmubooke_create_initial_mapping(env, 0, map_start, map_size); - - cpu->halted = 0; - cpu->exception_index = -1; - cpu->stopped = false; - qemu_cpu_kick(cpu); -} - -static void spin_write(void *opaque, hwaddr addr, uint64_t value, - unsigned len) -{ - SpinState *s = opaque; - int env_idx = addr / sizeof(SpinInfo); - CPUState *cpu; - SpinInfo *curspin = &s->spin[env_idx]; - uint8_t *curspin_p = (uint8_t*)curspin; - - cpu = qemu_get_cpu(env_idx); - if (cpu == NULL) { - /* Unknown CPU */ - return; - } - - if (cpu->cpu_index == 0) { - /* primary CPU doesn't spin */ - return; - } - - curspin_p = &curspin_p[addr % sizeof(SpinInfo)]; - switch (len) { - case 1: - stb_p(curspin_p, value); - break; - case 2: - stw_p(curspin_p, value); - break; - case 4: - stl_p(curspin_p, value); - break; - } - - if (!(ldq_p(&curspin->addr) & 1)) { - /* run CPU */ - SpinKick kick = { - .cpu = POWERPC_CPU(cpu), - .spin = curspin, - }; - - run_on_cpu(cpu, spin_kick, &kick); - } -} - -static uint64_t spin_read(void *opaque, hwaddr addr, unsigned len) -{ - SpinState *s = opaque; - uint8_t *spin_p = &((uint8_t*)s->spin)[addr]; - - switch (len) { - case 1: - return ldub_p(spin_p); - case 2: - return lduw_p(spin_p); - case 4: - return ldl_p(spin_p); - default: - hw_error("ppce500: unexpected %s with len = %u", __func__, len); - } -} - -static const MemoryRegionOps spin_rw_ops = { - .read = spin_read, - .write = spin_write, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static int ppce500_spin_initfn(SysBusDevice *dev) -{ - SpinState *s = E500_SPIN(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &spin_rw_ops, s, - "e500 spin pv device", sizeof(SpinInfo) * MAX_CPUS); - sysbus_init_mmio(dev, &s->iomem); - - qemu_register_reset(spin_reset, s); - - return 0; -} - -static void ppce500_spin_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = ppce500_spin_initfn; -} - -static const TypeInfo ppce500_spin_info = { - .name = TYPE_E500_SPIN, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SpinState), - .class_init = ppce500_spin_class_init, -}; - -static void ppce500_spin_register_types(void) -{ - type_register_static(&ppce500_spin_info); -} - -type_init(ppce500_spin_register_types) |