Introduction of write-combined memory type mappings.

Introduction of VR_WRITE_COMBINED, PTATTR_WRITE_COMBINED and modification
to the memobj's get_page() interface so that Linux communicates back mapping
flags (such as write-combined).
This commit is contained in:
Balazs Gerofi
2015-03-05 15:43:43 +09:00
parent ea5681232e
commit bf12a5c45e
10 changed files with 46 additions and 12 deletions

View File

@ -32,6 +32,8 @@
#include <pager.h>
#include <string.h>
#include <syscall.h>
#include <process.h>
#define dkprintf(...) do { if (0) kprintf(__VA_ARGS__); } while (0)
#define ekprintf(...) kprintf(__VA_ARGS__)
@ -192,7 +194,7 @@ static void devobj_release(struct memobj *memobj)
return;
}
static int devobj_get_page(struct memobj *memobj, off_t off, int p2align, uintptr_t *physp)
static int devobj_get_page(struct memobj *memobj, off_t off, int p2align, uintptr_t *physp, unsigned long *flag)
{
const off_t pgoff = off >> PAGE_SHIFT;
struct devobj *obj = to_devobj(memobj);
@ -232,6 +234,14 @@ kprintf("ix: %ld\n", ix);
/* convert remote physical into local physical */
kprintf("devobj_get_page(%p %lx,%lx,%d):PFN_PRESENT before %#lx\n", memobj, obj->handle, off, p2align, pfn);
attr = pfn & ~PFN_PFN;
/* TODO: do an arch dependent PTE to mapping flag conversion
* instead of this inline check, also, we rely on having the
* same PAT config as Linux here.. */
if ((pfn & PFL1_PWT) && !(pfn & PFL1_PCD)) {
*flag |= VR_WRITE_COMBINED;
}
pfn = ihk_mc_map_memory(NULL, (pfn & PFN_PFN), PAGE_SIZE);
pfn &= PFN_PFN;
pfn |= attr;

View File

@ -385,7 +385,7 @@ out:
return;
}
static int fileobj_get_page(struct memobj *memobj, off_t off, int p2align, uintptr_t *physp)
static int fileobj_get_page(struct memobj *memobj, off_t off, int p2align, uintptr_t *physp, unsigned long *pflag)
{
struct process *proc = cpu_local_var(current);
struct fileobj *obj = to_fileobj(memobj);

View File

@ -34,7 +34,7 @@ struct memobj {
typedef void memobj_release_func_t(struct memobj *obj);
typedef void memobj_ref_func_t(struct memobj *obj);
typedef int memobj_get_page_func_t(struct memobj *obj, off_t off, int p2align, uintptr_t *physp);
typedef int memobj_get_page_func_t(struct memobj *obj, off_t off, int p2align, uintptr_t *physp, unsigned long *flag);
typedef uintptr_t memobj_copy_page_func_t(struct memobj *obj, uintptr_t orgphys, int p2align);
typedef int memobj_flush_page_func_t(struct memobj *obj, uintptr_t phys, size_t pgsize);
typedef int memobj_invalidate_page_func_t(struct memobj *obj, uintptr_t phys, size_t pgsize);
@ -63,10 +63,10 @@ static inline void memobj_ref(struct memobj *obj)
}
static inline int memobj_get_page(struct memobj *obj, off_t off,
int p2align, uintptr_t *physp)
int p2align, uintptr_t *physp, unsigned long *pflag)
{
if (obj->ops->get_page) {
return (*obj->ops->get_page)(obj, off, p2align, physp);
return (*obj->ops->get_page)(obj, off, p2align, physp, pflag);
}
return -ENXIO;
}

View File

@ -28,6 +28,7 @@
#define VR_RESERVED 0x2
#define VR_IO_NOCACHE 0x100
#define VR_REMOTE 0x200
#define VR_WRITE_COMBINED 0x400
#define VR_DEMAND_PAGING 0x1000
#define VR_PRIVATE 0x2000
#define VR_LOCKED 0x4000

View File

@ -881,8 +881,8 @@ enum ihk_mc_pt_attribute common_vrflag_to_ptattr(unsigned long flag, uint64_t fa
attr |= PTATTR_NO_EXECUTE;
}
if ((flag & VR_MEMTYPE_MASK) == VR_MEMTYPE_UC) {
attr |= PTATTR_UNCACHABLE;
if (flag & VR_WRITE_COMBINED) {
attr |= PTATTR_WRITE_COMBINED;
}
return attr;
@ -1376,6 +1376,7 @@ static int page_fault_process_memory_range(struct process_vm *vm, struct vm_rang
enum ihk_mc_pt_attribute attr;
uintptr_t phys;
struct page *page = NULL;
unsigned long memobj_flag = 0;
dkprintf("page_fault_process_memory_range(%p,%lx-%lx %lx,%lx,%lx)\n", vm, range->start, range->end, range->flag, fault_addr, reason);
ihk_mc_spinlock_lock_noirq(&vm->page_table_lock);
@ -1402,7 +1403,6 @@ static int page_fault_process_memory_range(struct process_vm *vm, struct vm_rang
pgsize = PAGE_SIZE;
p2align = PAGE_P2ALIGN;
}
attr = arch_vrflag_to_ptattr(range->flag, reason, ptep);
pgaddr = (void *)(fault_addr & ~(pgsize - 1));
if (!ptep || pte_is_null(ptep) || pte_is_fileoff(ptep, pgsize)) {
if (range->memobj) {
@ -1414,7 +1414,8 @@ static int page_fault_process_memory_range(struct process_vm *vm, struct vm_rang
else {
off = pte_get_off(ptep, pgsize);
}
error = memobj_get_page(range->memobj, off, p2align, &phys);
error = memobj_get_page(range->memobj, off, p2align,
&phys, &memobj_flag);
if (error) {
if (error != -ERESTART) {
}
@ -1440,7 +1441,16 @@ static int page_fault_process_memory_range(struct process_vm *vm, struct vm_rang
else {
phys = pte_get_phys(ptep);
}
page = phys_to_page(phys);
/* If Linux requested VR_WRITE_COMBINED, but the range is NOCACHE mapped,
* make sure we use VR_WRITE_COMBINED */
attr = arch_vrflag_to_ptattr(
(((memobj_flag & VR_WRITE_COMBINED) && (range->flag & VR_IO_NOCACHE)) ?
range->flag & ~(VR_IO_NOCACHE) : range->flag)
| memobj_flag, reason, ptep);
/*****/
if (((range->flag & VR_PRIVATE)
|| ((reason & PF_PATCH)

View File

@ -203,7 +203,7 @@ static void shmobj_ref(struct memobj *memobj)
}
static int shmobj_get_page(struct memobj *memobj, off_t off, int p2align,
uintptr_t *physp)
uintptr_t *physp, unsigned long *pflag)
{
struct shmobj *obj = to_shmobj(memobj);
int error;

View File

@ -165,7 +165,7 @@ out:
}
static int zeroobj_get_page(struct memobj *memobj, off_t off, int p2align,
uintptr_t *physp)
uintptr_t *physp, unsigned long *pflag)
{
int error;
struct zeroobj *obj = to_zeroobj(memobj);