From: Jan Kiszka Date: Thu, 7 Jan 2016 17:17:18 +0000 (+0100) Subject: core: Introduce and use mmio_perform_access X-Git-Url: https://rtime.felk.cvut.cz/gitweb/jailhouse.git/commitdiff_plain/a3ad286621b5f190c93d9d08cd2e6c2c31423bb1 core: Introduce and use mmio_perform_access Generalize arm_mmio_perform_access to mmio_perform_access which can also be used on other architectures, including those with 64-bit MMIO support. Signed-off-by: Jan Kiszka --- diff --git a/hypervisor/arch/arm/gic-common.c b/hypervisor/arch/arm/gic-common.c index 00da4cb..7bb6cd3 100644 --- a/hypervisor/arch/arm/gic-common.c +++ b/hypervisor/arch/arm/gic-common.c @@ -59,7 +59,7 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index, /* For SGIs or PPIs, let the caller do the mmio access */ if (!is_spi(first_irq)) { - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); return MMIO_HANDLED; } @@ -73,7 +73,7 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index, if (!mmio->is_write) { /* Restrict the read value */ - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); mmio->value &= access_mask; return MMIO_HANDLED; } @@ -89,18 +89,18 @@ restrict_bitmask_access(struct mmio_access *mmio, unsigned int reg_index, spin_lock(&dist_lock); mmio->is_write = false; - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); mmio->is_write = true; /* Clear 0 bits */ mmio->value &= ~(access_mask & ~access_val); mmio->value |= access_val; - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); spin_unlock(&dist_lock); } else { mmio->value &= access_mask; - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); } return MMIO_HANDLED; } @@ -137,7 +137,7 @@ static enum mmio_result handle_irq_route(struct mmio_access *mmio, printk("Attempt to route IRQ%d outside of cell\n", irq); return MMIO_ERROR; } - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); } else { cpu = mmio_read32(gicd_base + GICD_IROUTER + 8 * irq); mmio->value = arm_cpu_phys2virt(cpu); @@ -167,7 +167,7 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio, * fill its CPU interface map. */ if (!is_spi(reg)) { - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); return MMIO_HANDLED; } @@ -212,10 +212,10 @@ static enum mmio_result handle_irq_target(struct mmio_access *mmio, /* Combine with external SPIs */ mmio->value |= (itargetsr & ~access_mask); /* And do the access */ - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); spin_unlock(&dist_lock); } else { - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); mmio->value &= access_mask; } @@ -350,7 +350,7 @@ enum mmio_result gic_handle_dist_access(void *arg, struct mmio_access *mmio) case REG_RANGE(GICD_CIDR0, 4, 4): /* Allow read access, ignore write */ if (!mmio->is_write) - arm_mmio_perform_access((unsigned long)gicd_base, mmio); + mmio_perform_access(gicd_base, mmio); /* fall through */ default: /* Ignore access. */ diff --git a/hypervisor/arch/arm/gic-v3.c b/hypervisor/arch/arm/gic-v3.c index 3a759f9..11cd5eb 100644 --- a/hypervisor/arch/arm/gic-v3.c +++ b/hypervisor/arch/arm/gic-v3.c @@ -263,7 +263,7 @@ static enum mmio_result gic_handle_redist_access(void *arg, return MMIO_HANDLED; } } - arm_mmio_perform_access((unsigned long)phys_redist, mmio); + mmio_perform_access((unsigned long)phys_redist, mmio); return MMIO_HANDLED; } diff --git a/hypervisor/arch/arm/include/asm/mmio.h b/hypervisor/arch/arm/include/asm/mmio.h index 1d44541..09cbc04 100644 --- a/hypervisor/arch/arm/include/asm/mmio.h +++ b/hypervisor/arch/arm/include/asm/mmio.h @@ -1,15 +1 @@ -/* - * Jailhouse, a Linux-based partitioning hypervisor - * - * Copyright (c) ARM Limited, 2014 - * - * Authors: - * Jean-Philippe Brucker - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - */ - -struct mmio_access; - -void arm_mmio_perform_access(unsigned long base, struct mmio_access *mmio); +/* nothing to do here */ diff --git a/hypervisor/arch/arm/mmio.c b/hypervisor/arch/arm/mmio.c index ec1fa3d..1098e8d 100644 --- a/hypervisor/arch/arm/mmio.c +++ b/hypervisor/arch/arm/mmio.c @@ -61,36 +61,6 @@ static void arch_inject_dabt(struct trap_context *ctx, unsigned long addr) arm_write_sysreg(DFAR, addr); } -void arm_mmio_perform_access(unsigned long base, struct mmio_access *mmio) -{ - void *addr = (void *)(base + mmio->address); - - if (mmio->is_write) - switch (mmio->size) { - case 1: - mmio_write8(addr, mmio->value); - return; - case 2: - mmio_write16(addr, mmio->value); - return; - case 4: - mmio_write32(addr, mmio->value); - return; - } - else - switch (mmio->size) { - case 1: - mmio->value = mmio_read8(addr); - return; - case 2: - mmio->value = mmio_read16(addr); - return; - case 4: - mmio->value = mmio_read32(addr); - return; - } -} - int arch_handle_dabt(struct trap_context *ctx) { enum mmio_result mmio_result; diff --git a/hypervisor/include/jailhouse/mmio.h b/hypervisor/include/jailhouse/mmio.h index 8c2a22c..907fa56 100644 --- a/hypervisor/include/jailhouse/mmio.h +++ b/hypervisor/include/jailhouse/mmio.h @@ -169,6 +169,8 @@ enum mmio_result mmio_handle_access(struct mmio_access *mmio); void mmio_cell_exit(struct cell *cell); +void mmio_perform_access(void *base, struct mmio_access *mmio); + unsigned int arch_mmio_count_regions(struct cell *cell); /** @} */ diff --git a/hypervisor/mmio.c b/hypervisor/mmio.c index a64093c..6fbe414 100644 --- a/hypervisor/mmio.c +++ b/hypervisor/mmio.c @@ -219,3 +219,43 @@ void mmio_cell_exit(struct cell *cell) (sizeof(struct mmio_region_location) + sizeof(struct mmio_region_handler)))); } + +void mmio_perform_access(void *base, struct mmio_access *mmio) +{ + void *addr = base + mmio->address; + + if (mmio->is_write) + switch (mmio->size) { + case 1: + mmio_write8(addr, mmio->value); + break; + case 2: + mmio_write16(addr, mmio->value); + break; + case 4: + mmio_write32(addr, mmio->value); + break; +#if BITS_PER_LONG == 64 + case 8: + mmio_write64(addr, mmio->value); + break; +#endif + } + else + switch (mmio->size) { + case 1: + mmio->value = mmio_read8(addr); + break; + case 2: + mmio->value = mmio_read16(addr); + break; + case 4: + mmio->value = mmio_read32(addr); + break; +#if BITS_PER_LONG == 64 + case 8: + mmio->value = mmio_read64(addr); + break; +#endif + } +}