mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180116' into staging
target-arm queue: * SDHCI: cleanups and minor bug fixes * target/arm: minor refactor preparatory to fp16 support * omap_ssd, ssi-sd, pl181, milkymist-memcard: reset the SD card on controller reset (fixes migration failures) * target/arm: Handle page table walk load failures correctly * hw/arm/virt: Add virt-2.12 machine type * get_phys_addr_pmsav7: Support AP=0b111 for v7M * hw/intc/armv7m: Support byte and halfword accesses to CFSR # gpg: Signature made Tue 16 Jan 2018 13:33:31 GMT # gpg: using RSA key 0x3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180116: (24 commits) sdhci: add a 'dma' property to the sysbus devices sdhci: fix the PCI device, using the PCI address space for DMA sdhci: Implement write method of ACMD12ERRSTS register sdhci: fix CAPAB/MAXCURR registers, both are 64bit and read-only sdhci: rename the SDHC_CAPAB register sdhci: move MASK_TRNMOD with other SDHC_TRN* defines in "sd-internal.h" sdhci: convert the DPRINT() calls into trace events sdhci: use qemu_log_mask(UNIMP) instead of fprintf() sdhci: refactor common sysbus/pci unrealize() into sdhci_common_unrealize() sdhci: refactor common sysbus/pci realize() into sdhci_common_realize() sdhci: refactor common sysbus/pci class_init() into sdhci_common_class_init() sdhci: use DEFINE_SDHCI_COMMON_PROPERTIES() for common sysbus/pci properties sdhci: remove dead code sdhci: clean up includes target/arm: Add fp16 support to vfp_expand_imm target/arm: Split out vfp_expand_imm hw/sd/omap_mmc: Reset SD card on controller reset hw/sd/ssi-sd: Reset SD card on controller reset hw/sd/milkymist-memcard: Reset SD card on controller reset hw/sd/pl181: Reset SD card on controller reset ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+18
-3
@@ -1618,7 +1618,7 @@ static void machvirt_machine_init(void)
|
||||
}
|
||||
type_init(machvirt_machine_init);
|
||||
|
||||
static void virt_2_11_instance_init(Object *obj)
|
||||
static void virt_2_12_instance_init(Object *obj)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
@@ -1678,10 +1678,25 @@ static void virt_2_11_instance_init(Object *obj)
|
||||
vms->irqmap = a15irqmap;
|
||||
}
|
||||
|
||||
static void virt_machine_2_11_options(MachineClass *mc)
|
||||
static void virt_machine_2_12_options(MachineClass *mc)
|
||||
{
|
||||
}
|
||||
DEFINE_VIRT_MACHINE_AS_LATEST(2, 11)
|
||||
DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
|
||||
|
||||
#define VIRT_COMPAT_2_11 \
|
||||
HW_COMPAT_2_11
|
||||
|
||||
static void virt_2_11_instance_init(Object *obj)
|
||||
{
|
||||
virt_2_12_instance_init(obj);
|
||||
}
|
||||
|
||||
static void virt_machine_2_11_options(MachineClass *mc)
|
||||
{
|
||||
virt_machine_2_12_options(mc);
|
||||
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 11)
|
||||
|
||||
#define VIRT_COMPAT_2_10 \
|
||||
HW_COMPAT_2_10
|
||||
|
||||
+22
-16
@@ -896,13 +896,6 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
|
||||
val |= (1 << 8);
|
||||
}
|
||||
return val;
|
||||
case 0xd28: /* Configurable Fault Status. */
|
||||
/* The BFSR bits [15:8] are shared between security states
|
||||
* and we store them in the NS copy
|
||||
*/
|
||||
val = cpu->env.v7m.cfsr[attrs.secure];
|
||||
val |= cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
|
||||
return val;
|
||||
case 0xd2c: /* Hard Fault Status. */
|
||||
return cpu->env.v7m.hfsr;
|
||||
case 0xd30: /* Debug Fault Status. */
|
||||
@@ -1280,15 +1273,6 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
|
||||
s->vectors[ARMV7M_EXCP_DEBUG].active = (value & (1 << 8)) != 0;
|
||||
nvic_irq_update(s);
|
||||
break;
|
||||
case 0xd28: /* Configurable Fault Status. */
|
||||
cpu->env.v7m.cfsr[attrs.secure] &= ~value; /* W1C */
|
||||
if (attrs.secure) {
|
||||
/* The BFSR bits [15:8] are shared between security states
|
||||
* and we store them in the NS copy.
|
||||
*/
|
||||
cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
|
||||
}
|
||||
break;
|
||||
case 0xd2c: /* Hard Fault Status. */
|
||||
cpu->env.v7m.hfsr &= ~value; /* W1C */
|
||||
break;
|
||||
@@ -1667,6 +1651,14 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
|
||||
val = deposit32(val, i * 8, 8, get_prio(s, hdlidx, sbank));
|
||||
}
|
||||
break;
|
||||
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
|
||||
/* The BFSR bits [15:8] are shared between security states
|
||||
* and we store them in the NS copy
|
||||
*/
|
||||
val = s->cpu->env.v7m.cfsr[attrs.secure];
|
||||
val |= s->cpu->env.v7m.cfsr[M_REG_NS] & R_V7M_CFSR_BFSR_MASK;
|
||||
val = extract32(val, (offset - 0xd28) * 8, size * 8);
|
||||
break;
|
||||
case 0xfe0 ... 0xfff: /* ID. */
|
||||
if (offset & 3) {
|
||||
val = 0;
|
||||
@@ -1765,6 +1757,20 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
|
||||
}
|
||||
nvic_irq_update(s);
|
||||
return MEMTX_OK;
|
||||
case 0xd28 ... 0xd2b: /* Configurable Fault Status (CFSR) */
|
||||
/* All bits are W1C, so construct 32 bit value with 0s in
|
||||
* the parts not written by the access size
|
||||
*/
|
||||
value <<= ((offset - 0xd28) * 8);
|
||||
|
||||
s->cpu->env.v7m.cfsr[attrs.secure] &= ~value;
|
||||
if (attrs.secure) {
|
||||
/* The BFSR bits [15:8] are shared between security states
|
||||
* and we store them in the NS copy.
|
||||
*/
|
||||
s->cpu->env.v7m.cfsr[M_REG_NS] &= ~(value & R_V7M_CFSR_BFSR_MASK);
|
||||
}
|
||||
return MEMTX_OK;
|
||||
}
|
||||
if (size == 4) {
|
||||
nvic_writel(s, offset, value, attrs);
|
||||
|
||||
@@ -248,6 +248,10 @@ static void milkymist_memcard_reset(DeviceState *d)
|
||||
for (i = 0; i < R_MAX; i++) {
|
||||
s->regs[i] = 0;
|
||||
}
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually.
|
||||
*/
|
||||
device_reset(DEVICE(s->card));
|
||||
}
|
||||
|
||||
static int milkymist_memcard_init(SysBusDevice *dev)
|
||||
|
||||
+10
-4
@@ -305,6 +305,12 @@ void omap_mmc_reset(struct omap_mmc_s *host)
|
||||
host->cdet_enable = 0;
|
||||
qemu_set_irq(host->coverswitch, host->cdet_state);
|
||||
host->clkdiv = 0;
|
||||
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually. When omap_mmc is
|
||||
* QOMified this must move into the QOM reset function.
|
||||
*/
|
||||
device_reset(DEVICE(host->card));
|
||||
}
|
||||
|
||||
static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
|
||||
@@ -587,8 +593,6 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
|
||||
s->lines = 1; /* TODO: needs to be settable per-board */
|
||||
s->rev = 1;
|
||||
|
||||
omap_mmc_reset(s);
|
||||
|
||||
memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", 0x800);
|
||||
memory_region_add_subregion(sysmem, base, &s->iomem);
|
||||
|
||||
@@ -598,6 +602,8 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
omap_mmc_reset(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -613,8 +619,6 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
|
||||
s->lines = 4;
|
||||
s->rev = 2;
|
||||
|
||||
omap_mmc_reset(s);
|
||||
|
||||
memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc",
|
||||
omap_l4_region_size(ta, 0));
|
||||
omap_l4_attach(ta, 0, &s->iomem);
|
||||
@@ -628,6 +632,8 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
|
||||
s->cdet = qemu_allocate_irq(omap_mmc_cover_cb, s, 0);
|
||||
sd_set_cb(s->card, NULL, s->cdet);
|
||||
|
||||
omap_mmc_reset(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -480,6 +480,10 @@ static void pl181_reset(DeviceState *d)
|
||||
|
||||
/* We can assume our GPIO outputs have been wired up now */
|
||||
sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually.
|
||||
*/
|
||||
device_reset(DEVICE(s->card));
|
||||
}
|
||||
|
||||
static void pl181_init(Object *obj)
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#ifndef SDHCI_INTERNAL_H
|
||||
#define SDHCI_INTERNAL_H
|
||||
|
||||
#include "hw/sd/sdhci.h"
|
||||
|
||||
/* R/W SDMA System Address register 0x0 */
|
||||
#define SDHC_SYSAD 0x00
|
||||
|
||||
@@ -45,6 +43,7 @@
|
||||
#define SDHC_TRNS_ACMD12 0x0004
|
||||
#define SDHC_TRNS_READ 0x0010
|
||||
#define SDHC_TRNS_MULTI 0x0020
|
||||
#define SDHC_TRNMOD_MASK 0x0037
|
||||
|
||||
/* R/W Command Register 0x0 */
|
||||
#define SDHC_CMDREG 0x0E
|
||||
@@ -175,7 +174,7 @@
|
||||
#define SDHC_ACMD12ERRSTS 0x3C
|
||||
|
||||
/* HWInit Capabilities Register 0x05E80080 */
|
||||
#define SDHC_CAPAREG 0x40
|
||||
#define SDHC_CAPAB 0x40
|
||||
#define SDHC_CAN_DO_DMA 0x00400000
|
||||
#define SDHC_CAN_DO_ADMA2 0x00080000
|
||||
#define SDHC_CAN_DO_ADMA1 0x00100000
|
||||
@@ -227,6 +226,4 @@ enum {
|
||||
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
|
||||
};
|
||||
|
||||
extern const VMStateDescription sdhci_vmstate;
|
||||
|
||||
#endif
|
||||
|
||||
+161
-105
File diff suppressed because it is too large
Load Diff
+23
-2
@@ -50,6 +50,9 @@ typedef struct {
|
||||
SDState *sd;
|
||||
} ssi_sd_state;
|
||||
|
||||
#define TYPE_SSI_SD "ssi-sd"
|
||||
#define SSI_SD(obj) OBJECT_CHECK(ssi_sd_state, (obj), TYPE_SSI_SD)
|
||||
|
||||
/* State word bits. */
|
||||
#define SSI_SDR_LOCKED 0x0001
|
||||
#define SSI_SDR_WP_ERASE 0x0002
|
||||
@@ -241,7 +244,6 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
|
||||
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
|
||||
DriveInfo *dinfo;
|
||||
|
||||
s->mode = SSI_SD_CMD;
|
||||
/* FIXME use a qdev drive property instead of drive_get_next() */
|
||||
dinfo = drive_get_next(IF_SD);
|
||||
s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
|
||||
@@ -251,6 +253,24 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void ssi_sd_reset(DeviceState *dev)
|
||||
{
|
||||
ssi_sd_state *s = SSI_SD(dev);
|
||||
|
||||
s->mode = SSI_SD_CMD;
|
||||
s->cmd = 0;
|
||||
memset(s->cmdarg, 0, sizeof(s->cmdarg));
|
||||
memset(s->response, 0, sizeof(s->response));
|
||||
s->arglen = 0;
|
||||
s->response_pos = 0;
|
||||
s->stopping = 0;
|
||||
|
||||
/* Since we're still using the legacy SD API the card is not plugged
|
||||
* into any bus, and we must reset it manually.
|
||||
*/
|
||||
device_reset(DEVICE(s->sd));
|
||||
}
|
||||
|
||||
static void ssi_sd_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@@ -260,10 +280,11 @@ static void ssi_sd_class_init(ObjectClass *klass, void *data)
|
||||
k->transfer = ssi_sd_transfer;
|
||||
k->cs_polarity = SSI_CS_LOW;
|
||||
dc->vmsd = &vmstate_ssi_sd;
|
||||
dc->reset = ssi_sd_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo ssi_sd_info = {
|
||||
.name = "ssi-sd",
|
||||
.name = TYPE_SSI_SD,
|
||||
.parent = TYPE_SSI_SLAVE,
|
||||
.instance_size = sizeof(ssi_sd_state),
|
||||
.class_init = ssi_sd_class_init,
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# hw/sd/sdhci.c
|
||||
sdhci_set_inserted(const char *level) "card state changed: %s"
|
||||
sdhci_send_command(uint8_t cmd, uint32_t arg) "CMD%02u ARG[0x%08x]"
|
||||
sdhci_error(const char *msg) "%s"
|
||||
sdhci_response4(uint32_t r0) "RSPREG[31..0]=0x%08x"
|
||||
sdhci_response16(uint32_t r3, uint32_t r2, uint32_t r1, uint32_t r0) "RSPREG[127..96]=0x%08x, RSPREG[95..64]=0x%08x, RSPREG[63..32]=0x%08x, RSPREG[31..0]=0x%08x"
|
||||
sdhci_end_transfer(uint8_t cmd, uint32_t arg) "Automatically issue CMD%02u 0x%08x"
|
||||
sdhci_adma(const char *desc, uint32_t sysad) "%s: admasysaddr=0x%" PRIx32
|
||||
sdhci_adma_loop(uint64_t addr, uint16_t length, uint8_t attr) "addr=0x%08" PRIx64 ", len=%d, attr=0x%x"
|
||||
sdhci_adma_transfer_completed(void) ""
|
||||
sdhci_access(const char *access, unsigned int size, uint64_t offset, const char *dir, uint64_t val, uint64_t val2) "%s%u: addr[0x%04" PRIx64 "] %s 0x%08" PRIx64 " (%" PRIu64 ")"
|
||||
sdhci_read_dataport(uint16_t data_count) "all %u bytes of data have been read from input buffer"
|
||||
sdhci_write_dataport(uint16_t data_count) "write buffer filled with %u bytes of data"
|
||||
|
||||
# hw/sd/milkymist-memcard.c
|
||||
milkymist_memcard_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
|
||||
milkymist_memcard_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
|
||||
|
||||
+13
-6
@@ -26,26 +26,29 @@
|
||||
#define SDHCI_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/sd/sd.h"
|
||||
|
||||
/* SD/MMC host controller state */
|
||||
typedef struct SDHCIState {
|
||||
/*< private >*/
|
||||
union {
|
||||
PCIDevice pcidev;
|
||||
SysBusDevice busdev;
|
||||
};
|
||||
|
||||
/*< public >*/
|
||||
SDBus sdbus;
|
||||
MemoryRegion iomem;
|
||||
AddressSpace *dma_as;
|
||||
MemoryRegion *dma_mr;
|
||||
|
||||
QEMUTimer *insert_timer; /* timer for 'changing' sd card. */
|
||||
QEMUTimer *transfer_timer;
|
||||
qemu_irq eject_cb;
|
||||
qemu_irq ro_cb;
|
||||
qemu_irq irq;
|
||||
|
||||
/* Registers cleared on reset */
|
||||
uint32_t sdmasysad; /* SDMA System Address register */
|
||||
uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */
|
||||
uint16_t blkcnt; /* Blocks count for current transfer */
|
||||
@@ -70,19 +73,23 @@ typedef struct SDHCIState {
|
||||
uint16_t acmd12errsts; /* Auto CMD12 error status register */
|
||||
uint64_t admasysaddr; /* ADMA System Address Register */
|
||||
|
||||
uint32_t capareg; /* Capabilities Register */
|
||||
uint32_t maxcurr; /* Maximum Current Capabilities Register */
|
||||
/* Read-only registers */
|
||||
uint64_t capareg; /* Capabilities Register */
|
||||
uint64_t maxcurr; /* Maximum Current Capabilities Register */
|
||||
|
||||
uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */
|
||||
uint32_t buf_maxsz;
|
||||
uint16_t data_count; /* current element in FIFO buffer */
|
||||
uint8_t stopped_state;/* Current SDHC state */
|
||||
bool pending_insert_quirk;/* Quirk for Raspberry Pi card insert int */
|
||||
bool pending_insert_state;
|
||||
/* Buffer Data Port Register - virtual access point to R and W buffers */
|
||||
/* Software Reset Register - always reads as 0 */
|
||||
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
|
||||
/* Force Event Error Interrupt Register- write only */
|
||||
/* RO Host Controller Version Register always reads as 0x2401 */
|
||||
|
||||
/* Configurable properties */
|
||||
bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
|
||||
} SDHCIState;
|
||||
|
||||
#define TYPE_PCI_SDHCI "sdhci-pci"
|
||||
|
||||
+48
-5
@@ -8305,6 +8305,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
|
||||
ret = get_phys_addr_lpae(env, addr, 0, ARMMMUIdx_S2NS, &s2pa,
|
||||
&txattrs, &s2prot, &s2size, fi, NULL);
|
||||
if (ret) {
|
||||
assert(fi->type != ARMFault_None);
|
||||
fi->s2addr = addr;
|
||||
fi->stage2 = true;
|
||||
fi->s1ptw = true;
|
||||
@@ -8328,7 +8329,9 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
MemTxAttrs attrs = {};
|
||||
MemTxResult result = MEMTX_OK;
|
||||
AddressSpace *as;
|
||||
uint32_t data;
|
||||
|
||||
attrs.secure = is_secure;
|
||||
as = arm_addressspace(cs, attrs);
|
||||
@@ -8337,10 +8340,16 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure,
|
||||
return 0;
|
||||
}
|
||||
if (regime_translation_big_endian(env, mmu_idx)) {
|
||||
return address_space_ldl_be(as, addr, attrs, NULL);
|
||||
data = address_space_ldl_be(as, addr, attrs, &result);
|
||||
} else {
|
||||
return address_space_ldl_le(as, addr, attrs, NULL);
|
||||
data = address_space_ldl_le(as, addr, attrs, &result);
|
||||
}
|
||||
if (result == MEMTX_OK) {
|
||||
return data;
|
||||
}
|
||||
fi->type = ARMFault_SyncExternalOnWalk;
|
||||
fi->ea = arm_extabort_type(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
|
||||
@@ -8349,7 +8358,9 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
MemTxAttrs attrs = {};
|
||||
MemTxResult result = MEMTX_OK;
|
||||
AddressSpace *as;
|
||||
uint32_t data;
|
||||
|
||||
attrs.secure = is_secure;
|
||||
as = arm_addressspace(cs, attrs);
|
||||
@@ -8358,10 +8369,16 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
|
||||
return 0;
|
||||
}
|
||||
if (regime_translation_big_endian(env, mmu_idx)) {
|
||||
return address_space_ldq_be(as, addr, attrs, NULL);
|
||||
data = address_space_ldq_be(as, addr, attrs, &result);
|
||||
} else {
|
||||
return address_space_ldq_le(as, addr, attrs, NULL);
|
||||
data = address_space_ldq_le(as, addr, attrs, &result);
|
||||
}
|
||||
if (result == MEMTX_OK) {
|
||||
return data;
|
||||
}
|
||||
fi->type = ARMFault_SyncExternalOnWalk;
|
||||
fi->ea = arm_extabort_type(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
|
||||
@@ -8390,6 +8407,9 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
|
||||
}
|
||||
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
|
||||
mmu_idx, fi);
|
||||
if (fi->type != ARMFault_None) {
|
||||
goto do_fault;
|
||||
}
|
||||
type = (desc & 3);
|
||||
domain = (desc >> 5) & 0x0f;
|
||||
if (regime_el(env, mmu_idx) == 1) {
|
||||
@@ -8426,6 +8446,9 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
|
||||
}
|
||||
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
|
||||
mmu_idx, fi);
|
||||
if (fi->type != ARMFault_None) {
|
||||
goto do_fault;
|
||||
}
|
||||
switch (desc & 3) {
|
||||
case 0: /* Page translation fault. */
|
||||
fi->type = ARMFault_Translation;
|
||||
@@ -8508,6 +8531,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
|
||||
}
|
||||
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
|
||||
mmu_idx, fi);
|
||||
if (fi->type != ARMFault_None) {
|
||||
goto do_fault;
|
||||
}
|
||||
type = (desc & 3);
|
||||
if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
|
||||
/* Section translation fault, or attempt to use the encoding
|
||||
@@ -8559,6 +8585,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
|
||||
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
|
||||
desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx),
|
||||
mmu_idx, fi);
|
||||
if (fi->type != ARMFault_None) {
|
||||
goto do_fault;
|
||||
}
|
||||
ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
|
||||
switch (desc & 3) {
|
||||
case 0: /* Page translation fault. */
|
||||
@@ -8964,7 +8993,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
|
||||
descaddr &= ~7ULL;
|
||||
nstable = extract32(tableattrs, 4, 1);
|
||||
descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fi);
|
||||
if (fi->s1ptw) {
|
||||
if (fi->type != ARMFault_None) {
|
||||
goto do_fault;
|
||||
}
|
||||
|
||||
@@ -9272,6 +9301,13 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
|
||||
case 6:
|
||||
*prot |= PAGE_READ | PAGE_EXEC;
|
||||
break;
|
||||
case 7:
|
||||
/* for v7M, same as 6; for R profile a reserved value */
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
*prot |= PAGE_READ | PAGE_EXEC;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"DRACR[%d]: Bad value for AP bits: 0x%"
|
||||
@@ -9290,6 +9326,13 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
|
||||
case 6:
|
||||
*prot |= PAGE_READ | PAGE_EXEC;
|
||||
break;
|
||||
case 7:
|
||||
/* for v7M, same as 6; for R profile a reserved value */
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
*prot |= PAGE_READ | PAGE_EXEC;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"DRACR[%d]: Bad value for AP bits: 0x%"
|
||||
|
||||
@@ -687,6 +687,16 @@ static inline uint32_t arm_fi_to_lfsc(ARMMMUFaultInfo *fi)
|
||||
return fsc;
|
||||
}
|
||||
|
||||
static inline bool arm_extabort_type(MemTxResult result)
|
||||
{
|
||||
/* The EA bit in syndromes and fault status registers is an
|
||||
* IMPDEF classification of external aborts. ARM implementations
|
||||
* usually use this to indicate AXI bus Decode error (0) or
|
||||
* Slave error (1); in QEMU we follow that.
|
||||
*/
|
||||
return result != MEMTX_DECODE_ERROR;
|
||||
}
|
||||
|
||||
/* Do a page table walk and add page to TLB if possible */
|
||||
bool arm_tlb_fill(CPUState *cpu, vaddr address,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
|
||||
@@ -220,12 +220,7 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
||||
/* now we have a real cpu fault */
|
||||
cpu_restore_state(cs, retaddr);
|
||||
|
||||
/* The EA bit in syndromes and fault status registers is an
|
||||
* IMPDEF classification of external aborts. ARM implementations
|
||||
* usually use this to indicate AXI bus Decode error (0) or
|
||||
* Slave error (1); in QEMU we follow that.
|
||||
*/
|
||||
fi.ea = (response != MEMTX_DECODE_ERROR);
|
||||
fi.ea = arm_extabort_type(response);
|
||||
fi.type = ARMFault_SyncExternal;
|
||||
deliver_fault(cpu, addr, access_type, mmu_idx, &fi);
|
||||
}
|
||||
|
||||
+33
-16
@@ -4985,6 +4985,38 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
|
||||
}
|
||||
}
|
||||
|
||||
/* The imm8 encodes the sign bit, enough bits to represent an exponent in
|
||||
* the range 01....1xx to 10....0xx, and the most significant 4 bits of
|
||||
* the mantissa; see VFPExpandImm() in the v8 ARM ARM.
|
||||
*/
|
||||
static uint64_t vfp_expand_imm(int size, uint8_t imm8)
|
||||
{
|
||||
uint64_t imm;
|
||||
|
||||
switch (size) {
|
||||
case MO_64:
|
||||
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
|
||||
(extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
|
||||
extract32(imm8, 0, 6);
|
||||
imm <<= 48;
|
||||
break;
|
||||
case MO_32:
|
||||
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
|
||||
(extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
|
||||
(extract32(imm8, 0, 6) << 3);
|
||||
imm <<= 16;
|
||||
break;
|
||||
case MO_16:
|
||||
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
|
||||
(extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
|
||||
(extract32(imm8, 0, 6) << 6);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return imm;
|
||||
}
|
||||
|
||||
/* Floating point immediate
|
||||
* 31 30 29 28 24 23 22 21 20 13 12 10 9 5 4 0
|
||||
* +---+---+---+-----------+------+---+------------+-------+------+------+
|
||||
@@ -5008,22 +5040,7 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
|
||||
return;
|
||||
}
|
||||
|
||||
/* The imm8 encodes the sign bit, enough bits to represent
|
||||
* an exponent in the range 01....1xx to 10....0xx,
|
||||
* and the most significant 4 bits of the mantissa; see
|
||||
* VFPExpandImm() in the v8 ARM ARM.
|
||||
*/
|
||||
if (is_double) {
|
||||
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
|
||||
(extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
|
||||
extract32(imm8, 0, 6);
|
||||
imm <<= 48;
|
||||
} else {
|
||||
imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
|
||||
(extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
|
||||
(extract32(imm8, 0, 6) << 3);
|
||||
imm <<= 16;
|
||||
}
|
||||
imm = vfp_expand_imm(MO_32 + is_double, imm8);
|
||||
|
||||
tcg_res = tcg_const_i64(imm);
|
||||
write_fp_dreg(s, rd, tcg_res);
|
||||
|
||||
Reference in New Issue
Block a user