xilinx_spips: allow mmio execution
This allows to execute from the lqspi area. When the request_ptr is called the device loads 1024bytes from the SPI device. Then this code can be executed by the guest. Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
This commit is contained in:
parent
c935674635
commit
252b99baeb
@ -496,6 +496,18 @@ static const MemoryRegionOps spips_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void xilinx_qspips_invalidate_mmio_ptr(XilinxQSPIPS *q)
|
||||
{
|
||||
XilinxSPIPS *s = &q->parent_obj;
|
||||
|
||||
if (q->lqspi_cached_addr != ~0ULL) {
|
||||
/* Invalidate the current mapped mmio */
|
||||
memory_region_invalidate_mmio_ptr(&s->mmlqspi, q->lqspi_cached_addr,
|
||||
LQSPI_CACHE_SIZE);
|
||||
q->lqspi_cached_addr = ~0ULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void xilinx_qspips_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
@ -505,7 +517,7 @@ static void xilinx_qspips_write(void *opaque, hwaddr addr,
|
||||
addr >>= 2;
|
||||
|
||||
if (addr == R_LQSPI_CFG) {
|
||||
q->lqspi_cached_addr = ~0ULL;
|
||||
xilinx_qspips_invalidate_mmio_ptr(q);
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,27 +529,20 @@ static const MemoryRegionOps qspips_ops = {
|
||||
|
||||
#define LQSPI_CACHE_SIZE 1024
|
||||
|
||||
static uint64_t
|
||||
lqspi_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
static void lqspi_load_cache(void *opaque, hwaddr addr)
|
||||
{
|
||||
int i;
|
||||
XilinxQSPIPS *q = opaque;
|
||||
XilinxSPIPS *s = opaque;
|
||||
uint32_t ret;
|
||||
|
||||
if (addr >= q->lqspi_cached_addr &&
|
||||
addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
|
||||
uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
|
||||
ret = cpu_to_le32(*(uint32_t *)retp);
|
||||
DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
|
||||
(unsigned)ret);
|
||||
return ret;
|
||||
} else {
|
||||
int flash_addr = (addr / num_effective_busses(s));
|
||||
int slave = flash_addr >> LQSPI_ADDRESS_BITS;
|
||||
int cache_entry = 0;
|
||||
uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
|
||||
int i;
|
||||
int flash_addr = ((addr & ~(LQSPI_CACHE_SIZE - 1))
|
||||
/ num_effective_busses(s));
|
||||
int slave = flash_addr >> LQSPI_ADDRESS_BITS;
|
||||
int cache_entry = 0;
|
||||
uint32_t u_page_save = s->regs[R_LQSPI_STS] & ~LQSPI_CFG_U_PAGE;
|
||||
|
||||
if (addr < q->lqspi_cached_addr ||
|
||||
addr > q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
|
||||
xilinx_qspips_invalidate_mmio_ptr(q);
|
||||
s->regs[R_LQSPI_STS] &= ~LQSPI_CFG_U_PAGE;
|
||||
s->regs[R_LQSPI_STS] |= slave ? LQSPI_CFG_U_PAGE : 0;
|
||||
|
||||
@ -589,12 +594,43 @@ lqspi_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
xilinx_spips_update_cs_lines(s);
|
||||
|
||||
q->lqspi_cached_addr = flash_addr * num_effective_busses(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void *lqspi_request_mmio_ptr(void *opaque, hwaddr addr, unsigned *size,
|
||||
unsigned *offset)
|
||||
{
|
||||
XilinxQSPIPS *q = opaque;
|
||||
hwaddr offset_within_the_region = addr & ~(LQSPI_CACHE_SIZE - 1);
|
||||
|
||||
lqspi_load_cache(opaque, offset_within_the_region);
|
||||
*size = LQSPI_CACHE_SIZE;
|
||||
*offset = offset_within_the_region;
|
||||
return q->lqspi_buf;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
lqspi_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
XilinxQSPIPS *q = opaque;
|
||||
uint32_t ret;
|
||||
|
||||
if (addr >= q->lqspi_cached_addr &&
|
||||
addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) {
|
||||
uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr];
|
||||
ret = cpu_to_le32(*(uint32_t *)retp);
|
||||
DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr,
|
||||
(unsigned)ret);
|
||||
return ret;
|
||||
} else {
|
||||
lqspi_load_cache(opaque, addr);
|
||||
return lqspi_read(opaque, addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps lqspi_ops = {
|
||||
.read = lqspi_read,
|
||||
.request_ptr = lqspi_request_mmio_ptr,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
|
Loading…
Reference in New Issue
Block a user