This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

MMU initialization for an ARM multicore system

I am working on an Arria10 SoC which has dual ARM Cortex-A9 MPCore. And I work on bare-metal environment with Intel SoCFPGA’s hardware library(HwLib).

On the shared SDRAM, I am planning to have dedicated memory regions for each core, and a shared non-cacheable memory area. And the FPGA does not get involved in the SDRAM. But my attemps to initialize MMU fails.

Here is what I have done:

For CPU0:

static void mmu_init(void)
{
    uint32_t *ttb1 = NULL;

    /* Populate the page table with sections (1 MiB regions). */
    ALT_MMU_MEM_REGION_t regions[] = {
            /* CPU0 Memory area: 256 MB */
            {
                    .va         = (void *)0x00000000,
                    .pa         = (void *)0x00000000,
                    .size       = 0x10000000,
                    .access     = ALT_MMU_AP_FULL_ACCESS,
                    .attributes = ALT_MMU_ATTR_WBA,
                    .shareable  = ALT_MMU_TTB_S_NON_SHAREABLE,
                    .execute    = ALT_MMU_TTB_XN_DISABLE,
                    .security   = ALT_MMU_TTB_NS_SECURE
            },
            /* CPU1 Memory area: 512 MB */
            /* CPU0 MUST NOT ACCESS THIS AREA */
            {
                    .va         = (void *)0x10000000,
                    .pa         = (void *)0x10000000,
                    .size       = 0x20000000,
                    .access     = ALT_MMU_AP_NO_ACCESS,
                    .attributes = ALT_MMU_ATTR_FAULT,
                    .shareable  = ALT_MMU_TTB_S_NON_SHAREABLE,
                    .execute    = ALT_MMU_TTB_XN_DISABLE,
                    .security   = ALT_MMU_TTB_NS_SECURE
            },
            /* Shared Memory area: 256 MB */
            {
                    .va         = (void *)0x30000000,
                    .pa         = (void *)0x30000000,
                    .size       = 0x10000000,
                    .access     = ALT_MMU_AP_FULL_ACCESS,
                    .attributes = ALT_MMU_ATTR_DEVICE_NS,
                    .shareable  = ALT_MMU_TTB_S_NON_SHAREABLE,
                    .execute    = ALT_MMU_TTB_XN_ENABLE,
                    .security   = ALT_MMU_TTB_NS_SECURE
            },
            /* Device area: Everything else */
            {
                    .va         = (void *)0x40000000,
                    .pa         = (void *)0x40000000,
                    .size       = 0xc0000000,
                    .access     = ALT_MMU_AP_FULL_ACCESS,
                    .attributes = ALT_MMU_ATTR_DEVICE_NS,
                    .shareable  = ALT_MMU_TTB_S_NON_SHAREABLE,
                    .execute    = ALT_MMU_TTB_XN_ENABLE,
                    .security   = ALT_MMU_TTB_NS_SECURE
            }
    };

    assert(ALT_E_SUCCESS == alt_mmu_init());
    assert(alt_mmu_va_space_storage_required(regions, ARRAY_SIZE(regions)) <= sizeof(alt_pt_storage));
    assert(ALT_E_SUCCESS == alt_mmu_va_space_create(&ttb1, regions, ARRAY_SIZE(regions), alt_pt_alloc, alt_pt_storage));
    assert(ALT_E_SUCCESS == alt_mmu_va_space_enable(ttb1));
}


For CPU1: Same initialization with CPU0 and CPU1’s .access and .attributes variables swapped.

This configuration results a system hang at alt_mmu_va_space_enable() function.

Since each CPU has its own MMU, I think this configuration is necessary for memory safety. I don’t see any mechanism that handles intercore MMU and since each core has its own MMU, I think that this is the only way to implement a safe shared memory. Is my method and inference right? If so, what am I doing wrong? Thanks in advance.

Parents
  • I was not expecting any help on the software implementation side. I guess the code piece that is written using the HwLib in the question caused you to think that. Sorry if I couldn't expressed myself properly, and thank you for your kind answer.

    First of all, I can initialize MMU now. In my CPU1 code scatter file, I had arranged the init space as 0x01000000, but in MMU configuration, I had marked this region as "NO ACCESS". Giving CPU1 some space with 0x01000000 solved the problem. But I think my problem here is more on the 'concept' side of the subject. Because now I get runtime errors both on normal memory side and device are side (my serial terminal goes nuts sometimes, so I guess I am breaking something on device area) The questions I was talking about the previous post were: "Scatter file's relationship with MMU configuration", "using malloc() in a system with MMU enabled", "fragmented identity mapping" and so on... Those were the problems I had while testing the MMU configuration, and I don't even know if I'm testing it the right way.

    For example, to test fragmented MMU config (areas with the configurations: FULL ACCESS - NO ACCESS - FULL ACCESS, in this order), I am calling malloc() with 1 MB in a while loop to see which regions I can allocate. But after the first accessable area, the code gives an abort. I would expect it to see that the next accessible memory block, and continue allocating space from there...   

    I know it's hard to answer all of them in this medium, and it is clearly asking too much to say the least. So even a source suggestion or a little clue is really appreciated. Once again, thank you  for your interest.

Reply
  • I was not expecting any help on the software implementation side. I guess the code piece that is written using the HwLib in the question caused you to think that. Sorry if I couldn't expressed myself properly, and thank you for your kind answer.

    First of all, I can initialize MMU now. In my CPU1 code scatter file, I had arranged the init space as 0x01000000, but in MMU configuration, I had marked this region as "NO ACCESS". Giving CPU1 some space with 0x01000000 solved the problem. But I think my problem here is more on the 'concept' side of the subject. Because now I get runtime errors both on normal memory side and device are side (my serial terminal goes nuts sometimes, so I guess I am breaking something on device area) The questions I was talking about the previous post were: "Scatter file's relationship with MMU configuration", "using malloc() in a system with MMU enabled", "fragmented identity mapping" and so on... Those were the problems I had while testing the MMU configuration, and I don't even know if I'm testing it the right way.

    For example, to test fragmented MMU config (areas with the configurations: FULL ACCESS - NO ACCESS - FULL ACCESS, in this order), I am calling malloc() with 1 MB in a while loop to see which regions I can allocate. But after the first accessable area, the code gives an abort. I would expect it to see that the next accessible memory block, and continue allocating space from there...   

    I know it's hard to answer all of them in this medium, and it is clearly asking too much to say the least. So even a source suggestion or a little clue is really appreciated. Once again, thank you  for your interest.

Children
  • Are you sure the heap is correctly setup? I think it is easier to use just a pointer to test the MMU configuration instead of malloc(). A failing malloc() is no indication of a wrong MMU setup.
    Is the code of CPU1 in the correct area? A common fault is to "cut the branch you are sitting on". Means, you make the memory NX your code is in.