Skip to content
  • Bryan O'Donoghue's avatar
    x86/intel/quark: Add Isolated Memory Regions for Quark X1000 · 28a375df
    Bryan O'Donoghue authored
    
    
    Intel's Quark X1000 SoC contains a set of registers called
    Isolated Memory Regions. IMRs are accessed over the IOSF mailbox
    interface. IMRs are areas carved out of memory that define
    read/write access rights to the various system agents within the
    Quark system. For a given agent in the system it is possible to
    specify if that agent may read or write an area of memory
    defined by an IMR with a granularity of 1 KiB.
    
    Quark_SecureBootPRM_330234_001.pdf section 4.5 details the
    concept of IMRs quark-x1000-datasheet.pdf section 12.7.4 details
    the implementation of IMRs in silicon.
    
    eSRAM flush, CPU Snoop write-only, CPU SMM Mode, CPU non-SMM
    mode, RMU and PCIe Virtual Channels (VC0 and VC1) can have
    individual read/write access masks applied to them for a given
    memory region in Quark X1000. This enables IMRs to treat each
    memory transaction type listed above on an individual basis and
    to filter appropriately based on the IMR access mask for the
    memory region. Quark supports eight IMRs.
    
    Since all of the DMA capable SoC components in the X1000 are
    mapped to VC0 it is possible to define sections of memory as
    invalid for DMA write operations originating from Ethernet, USB,
    SD and any other DMA capable south-cluster component on VC0.
    Similarly it is possible to mark kernel memory as non-SMM mode
    read/write only or to mark BIOS runtime memory as SMM mode
    accessible only depending on the particular memory footprint on
    a given system.
    
    On an IMR violation Quark SoC X1000 systems are configured to
    reset the system, so ensuring that the IMR memory map is
    consistent with the EFI provided memory map is critical to
    ensure no IMR violations reset the system.
    
    The API for accessing IMRs is based on MTRR code but doesn't
    provide a /proc or /sys interface to manipulate IMRs. Defining
    the size and extent of IMRs is exclusively the domain of
    in-kernel code.
    
    Quark firmware sets up a series of locked IMRs around pieces of
    memory that firmware owns such as ACPI runtime data. During boot
    a series of unlocked IMRs are placed around items in memory to
    guarantee no DMA modification of those items can take place.
    Grub also places an unlocked IMR around the kernel boot params
    data structure and compressed kernel image. It is necessary for
    the kernel to tear down all unlocked IMRs in order to ensure
    that the kernel's view of memory passed via the EFI memory map
    is consistent with the IMR memory map. Without tearing down all
    unlocked IMRs on boot transitory IMRs such as those used to
    protect the compressed kernel image will cause IMR violations and system reboots.
    
    The IMR init code tears down all unlocked IMRs and sets a
    protective IMR around the kernel .text and .rodata as one
    contiguous block. This sanitizes the IMR memory map with respect
    to the EFI memory map and protects the read-only portions of the
    kernel from unwarranted DMA access.
    
    Tested-by: default avatarOng, Boon Leong <boon.leong.ong@intel.com>
    Signed-off-by: default avatarBryan O'Donoghue <pure.logic@nexus-software.ie>
    Reviewed-by: default avatarAndy Shevchenko <andy.schevchenko@gmail.com>
    Reviewed-by: default avatarDarren Hart <dvhart@linux.intel.com>
    Reviewed-by: default avatarOng, Boon Leong <boon.leong.ong@intel.com>
    Cc: andy.shevchenko@gmail.com
    Cc: dvhart@infradead.org
    Link: http://lkml.kernel.org/r/1422635379-12476-2-git-send-email-pure.logic@nexus-software.ie
    
    
    Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
    28a375df