x86: MMU: Memory domain implementation for x86
Added support for memory domain implementation. GH-3852 Signed-off-by: Adithya Baglody <adithya.nagaraj.baglody@intel.com>
This commit is contained in:
parent
7add3cdd82
commit
d0f6ce2d98
3 changed files with 175 additions and 1 deletions
|
@ -113,6 +113,7 @@ static inline void tlb_flush_page(void *addr)
|
||||||
* specified address
|
* specified address
|
||||||
*/
|
*/
|
||||||
char *page = (char *)addr;
|
char *page = (char *)addr;
|
||||||
|
|
||||||
__asm__ ("invlpg %0" :: "m" (*page));
|
__asm__ ("invlpg %0" :: "m" (*page));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,3 +141,107 @@ void _x86_mmu_set_flags(void *ptr, size_t size, u32_t flags, u32_t mask)
|
||||||
addr += MMU_PAGE_SIZE;
|
addr += MMU_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_USERSPACE
|
||||||
|
|
||||||
|
/* Helper macros needed to be passed to x86_update_mem_domain_pages */
|
||||||
|
#define X86_MEM_DOMAIN_SET_PAGES (0U)
|
||||||
|
#define X86_MEM_DOMAIN_RESET_PAGES (1U)
|
||||||
|
/* Pass 1 to page_conf if reset of mem domain pages is needed else pass a 0*/
|
||||||
|
static inline void x86_update_mem_domain_pages(struct k_mem_domain *mem_domain,
|
||||||
|
u32_t page_conf)
|
||||||
|
{
|
||||||
|
u32_t partition_index;
|
||||||
|
u32_t total_partitions;
|
||||||
|
struct k_mem_partition partition;
|
||||||
|
u32_t partitions_count;
|
||||||
|
|
||||||
|
/* If mem_domain doesn't point to a valid location return.*/
|
||||||
|
if (mem_domain == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the total number of partitions*/
|
||||||
|
total_partitions = mem_domain->num_partitions;
|
||||||
|
|
||||||
|
/* Iterate over all the partitions for the given mem_domain
|
||||||
|
* For x86: interate over all the partitions and set the
|
||||||
|
* required flags in the correct MMU page tables.
|
||||||
|
*/
|
||||||
|
partitions_count = 0;
|
||||||
|
for (partition_index = 0;
|
||||||
|
partitions_count < total_partitions;
|
||||||
|
partition_index++) {
|
||||||
|
|
||||||
|
/* Get the partition info */
|
||||||
|
partition = mem_domain->partitions[partition_index];
|
||||||
|
if (partition.size == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
partitions_count++;
|
||||||
|
if (page_conf == X86_MEM_DOMAIN_SET_PAGES) {
|
||||||
|
/* Set the partition attributes */
|
||||||
|
_x86_mmu_set_flags((void *)partition.start,
|
||||||
|
partition.size,
|
||||||
|
partition.attr,
|
||||||
|
K_MEM_PARTITION_PERM_MASK);
|
||||||
|
} else {
|
||||||
|
/* Reset the pages to supervisor RW only */
|
||||||
|
_x86_mmu_set_flags((void *)partition.start,
|
||||||
|
partition.size,
|
||||||
|
K_MEM_PARTITION_P_RW_U_NA,
|
||||||
|
K_MEM_PARTITION_PERM_MASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Load the required parttions of the new incoming thread */
|
||||||
|
void _x86_load_mmu_mem_domain(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
x86_update_mem_domain_pages(thread->mem_domain_info.mem_domain,
|
||||||
|
X86_MEM_DOMAIN_SET_PAGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy or reset the mmu page tables when necessary.
|
||||||
|
* Needed when either swap takes place or k_mem_domain_destroy is called.
|
||||||
|
*/
|
||||||
|
void _arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||||
|
{
|
||||||
|
x86_update_mem_domain_pages(domain, X86_MEM_DOMAIN_RESET_PAGES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset/destroy one partition spcified in the argument of the API. */
|
||||||
|
void _arch_mem_domain_remove_partition(struct k_mem_domain *domain,
|
||||||
|
u32_t partition_id)
|
||||||
|
{
|
||||||
|
u32_t total_partitions;
|
||||||
|
struct k_mem_partition partition;
|
||||||
|
|
||||||
|
if (domain == NULL) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_partitions = domain->num_partitions;
|
||||||
|
__ASSERT(partition_id <= total_partitions,
|
||||||
|
"invalid partitions");
|
||||||
|
|
||||||
|
partition = domain->partitions[partition_id];
|
||||||
|
|
||||||
|
_x86_mmu_set_flags((void *)partition.start,
|
||||||
|
partition.size,
|
||||||
|
K_MEM_PARTITION_P_RW_U_NA,
|
||||||
|
K_MEM_PARTITION_PERM_MASK);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8_t _arch_mem_domain_max_partitions_get(void)
|
||||||
|
{
|
||||||
|
return CONFIG_MAX_DOMAIN_PARTITIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_X86_USERSPACE*/
|
||||||
|
|
|
@ -137,7 +137,6 @@
|
||||||
#define MMU_ENTRY_RUNTIME_WRITE 0x20000000
|
#define MMU_ENTRY_RUNTIME_WRITE 0x20000000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper macros to ease the usage of the MMU page table structures.
|
/* Helper macros to ease the usage of the MMU page table structures.
|
||||||
* Returns the Page table address for the particular address.
|
* Returns the Page table address for the particular address.
|
||||||
* Page Table address(returned value) is always 4KBytes aligned.
|
* Page Table address(returned value) is always 4KBytes aligned.
|
||||||
|
@ -168,6 +167,63 @@
|
||||||
((union x86_mmu_pde_4mb *)\
|
((union x86_mmu_pde_4mb *)\
|
||||||
(&X86_MMU_PD->entry[MMU_PDE_NUM(addr)].fourmb))
|
(&X86_MMU_PD->entry[MMU_PDE_NUM(addr)].fourmb))
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_USERSPACE
|
||||||
|
|
||||||
|
/* Flags which are only available for PAE mode page tables */
|
||||||
|
#ifdef CONFIG_X86_PAE_MODE
|
||||||
|
|
||||||
|
/* memory partition arch/soc independent attribute */
|
||||||
|
#define K_MEM_PARTITION_P_RW_U_RW (MMU_ENTRY_WRITE | \
|
||||||
|
MMU_ENTRY_USER | \
|
||||||
|
MMU_ENTRY_EXECUTE_DISABLE)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RW_U_NA (MMU_ENTRY_WRITE | \
|
||||||
|
MMU_ENTRY_SUPERVISOR | \
|
||||||
|
MMU_ENTRY_EXECUTE_DISABLE)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RO_U_RO (MMU_ENTRY_READ | \
|
||||||
|
MMU_ENTRY_USER | \
|
||||||
|
MMU_ENTRY_EXECUTE_DISABLE)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RO_U_NA (MMU_ENTRY_READ | \
|
||||||
|
MMU_ENTRY_SUPERVISOR | \
|
||||||
|
MMU_ENTRY_EXECUTE_DISABLE)
|
||||||
|
|
||||||
|
/* Execution-allowed attributes */
|
||||||
|
#define K_MEM_PARTITION_P_RWX_U_RWX (MMU_ENTRY_WRITE | MMU_ENTRY_USER)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RWX_U_NA (MMU_ENTRY_WRITE | MMU_ENTRY_SUPERVISOR)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RX_U_RX (MMU_ENTRY_READ | MMU_ENTRY_USER)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RX_U_NA (MMU_ENTRY_READ | MMU_ENTRY_SUPERVISOR)
|
||||||
|
|
||||||
|
|
||||||
|
/* memory partition access permission mask */
|
||||||
|
#define K_MEM_PARTITION_PERM_MASK (MMU_PTE_RW_MASK |\
|
||||||
|
MMU_PTE_US_MASK |\
|
||||||
|
MMU_PTE_XD_MASK)
|
||||||
|
|
||||||
|
|
||||||
|
#else /* 32-bit paging mode enabled */
|
||||||
|
|
||||||
|
/* memory partition arch/soc independent attribute */
|
||||||
|
#define K_MEM_PARTITION_P_RW_U_RW (MMU_ENTRY_WRITE | MMU_ENTRY_USER)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RW_U_NA (MMU_ENTRY_WRITE | MMU_ENTRY_SUPERVISOR)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RO_U_RO (MMU_ENTRY_READ | MMU_ENTRY_USER)
|
||||||
|
|
||||||
|
#define K_MEM_PARTITION_P_RO_U_NA (MMU_ENTRY_READ | MMU_ENTRY_SUPERVISOR)
|
||||||
|
|
||||||
|
/* memory partition access permission mask */
|
||||||
|
#define K_MEM_PARTITION_PERM_MASK (MMU_PTE_RW_MASK | MMU_PTE_US_MASK)
|
||||||
|
|
||||||
|
#endif /* CONFIG_X86_PAE_MODE */
|
||||||
|
|
||||||
|
#endif /* CONFIG_X86_USERSPACE */
|
||||||
|
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE
|
#ifndef _ASMLANGUAGE
|
||||||
#include <zephyr/types.h>
|
#include <zephyr/types.h>
|
||||||
|
|
||||||
|
|
|
@ -787,6 +787,19 @@ void _x86_mmu_get_flags(void *addr, u32_t *pde_flags, u32_t *pte_flags);
|
||||||
* modify
|
* modify
|
||||||
*/
|
*/
|
||||||
void _x86_mmu_set_flags(void *ptr, size_t size, u32_t flags, u32_t mask);
|
void _x86_mmu_set_flags(void *ptr, size_t size, u32_t flags, u32_t mask);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
/**
|
||||||
|
* @brief Load the memory domain for the thread.
|
||||||
|
*
|
||||||
|
* If the memory domain is used this API will configure the page tables
|
||||||
|
* according to the memory domain partition attributes.
|
||||||
|
*
|
||||||
|
* @param thread k_thread structure for the thread which is to configured.
|
||||||
|
*/
|
||||||
|
void _x86_load_mmu_mem_domain(struct k_thread *thread);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_X86_MMU */
|
#endif /* CONFIG_X86_MMU */
|
||||||
|
|
||||||
#endif /* !_ASMLANGUAGE */
|
#endif /* !_ASMLANGUAGE */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue