OSDev.org
https://forum.osdev.org/

Qemu fw_cfg DMA aarch64
https://forum.osdev.org/viewtopic.php?f=1&t=33676
Page 1 of 1

Author:  foreverska [ Wed May 01, 2019 1:10 pm ]
Post subject:  Qemu fw_cfg DMA aarch64

I'm attempting DMA access of a fw_cfg file. I have accessed the directory, compared file names and found the file i want. I have compared the reported size to make sure it is correct for what I was expecting. All of these things are true and then I enter fwcfg_dma_access via

Code:
    #define FWCFG_DMA_READ    2
    fwcfg_dma_access(file.select << 16 | FWCFG_DMA_READ, ramfb_file.size, (vaddr_t) &cfg);


Code:
#if __ORDER_LITTLE_ENDIAN__
#define HTOBE(x)  __builtin_bswap32(x)
#define HTOBE64(x) __builtin_bswap64(x)
#else
#define HTOBE(x) x
#define HTOBE64(x) x
#endif

#define FW_CFG_BASE       0x09020000

#define FW_CFG_CTL_OFF       0x08
#define FW_CFG_DATA_OFF    0x00
#define FW_CFG_DMA_OFF       0x10

struct fwcfg_dma_access {
   uint32_t control;
   uint32_t length;
   uint64_t address;
};

static vaddr_t _addr(vaddr_t base, vaddr_t offset)
{
   return (vaddr_t) phys_to_virt(base, MEM_AREA_IO_SEC) + offset;
}

int fwcfg_dma_access(uint32_t ctrl, uint32_t len, vaddr_t addr)
{
   volatile struct fwcfg_dma_access access;
   
   access.control = HTOBE(ctrl);
   access.length = HTOBE(len);
   access.address = HTOBE64(addr);
   
   vaddr_t access_addr = (vaddr_t) virt_to_phys((void*) &access);
   uint32_t access_addr_lo = (uint32_t) (access_addr & 0xFFFFFFFFU);
   uint32_t access_addr_hi = (uint32_t) (access_addr >> 32);
   
   io_write32(_addr(FW_CFG_BASE, FW_CFG_DMA_OFF), HTOBE(access_addr_hi));
   io_write32(_addr(FW_CFG_BASE, FW_CFG_DMA_OFF + 4), HTOBE(access_addr_lo));
   
   DMSG("Waiting on DMA Access");
   while ((HTOBE(access.control) & ~FWCFG_DMA_ERROR) != 0) {}
   DMSG("DMA Access Done");
   
   return FWCFG_OK;
}


The execution gets to "waiting on DMA acess" but never reaches "DMA access done". I pulled the check from Linux kernel. I have also tried:

Code:
   DMSG("Waiting on DMA Access");
   while (io_read32(_addr(FW_CFG_BASE, FW_CFG_DMA_OFF)) != 0) {}
   DMSG("DMA Access Done");


with no success. Anyone have any hints?

Author:  foreverska [ Mon May 13, 2019 10:20 am ]
Post subject:  Re: Qemu fw_cfg DMA aarch64

For the posterity of future internet explorers this ended up being an issue in Qemu aarch64. Non-secure devices (FW_CFG at the time of this writing) cannot DMA secure memory (ie Secure ram). Make sure the devices are the same memory security levels.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/