Skip to content

Per-page capability-dirty tracking, take N+1 #405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions bin/cheribsdtest/cheribsdtest_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,3 +616,72 @@ CHERIBSDTEST(cheribsdtest_vm_cow_write,
CHERIBSDTEST_CHECK_SYSCALL(close(fd));
cheribsdtest_success();
}

/*
* Store a cap to a page and check that mincore reports it CAPSTORE.
*
* Due to a shortage of bits in mincore()'s uint8_t reporting bit vector, this
* particular test is not able to distinguish CAPSTORE and CAPDIRTY and so is
* not sensitive to the vm.pmap.enter_capstore_as_capdirty sysctl.
*
* On the other hand, this test is sensitive to the vm.capstore_on_alloc sysctl:
* if that is asserted, our cap-capable anonymous memory will be installed
* CAPSTORE (and possibly even CAPDIRTY, in light of the above) whereas, if this
* sysctl is clear, our initial view of said memory will be !CAPSTORE.
*/
CHERIBSDTEST(cheribsdtest_vm_capdirty, "verify capdirty marking and mincore")
{
static const size_t npg = 2;
size_t sz = npg * getpagesize();
uint8_t capstore_on_alloc;
size_t capstore_on_alloc_sz = sizeof(capstore_on_alloc);

void * __capability *pg0;
unsigned char mcv[npg] = { 0 };

CHERIBSDTEST_CHECK_SYSCALL(
sysctlbyname("vm.capstore_on_alloc", &capstore_on_alloc,
&capstore_on_alloc_sz, NULL, 0));

pg0 = CHERIBSDTEST_CHECK_SYSCALL(
mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0));

void * __capability *pg1 = (void *)&((char *)pg0)[getpagesize()];

/*
* Pages are ZFOD and so will not be CAPSTORE, or, really, anything
* else, either.
*/
CHERIBSDTEST_CHECK_SYSCALL(mincore(pg0, sz, &mcv[0]));
CHERIBSDTEST_VERIFY2(mcv[0] == 0, "page 0 status 0");
CHERIBSDTEST_VERIFY2(mcv[1] == 0, "page 1 status 0");

/*
* Write data to page 0, causing it to become allocated and MODIFIED.
* If vm.capstore_on_alloc, then it should be CAPSTORE as well, despite
* having never been the target of a capability store.
*/
*(char *)pg0 = 0x42;

CHERIBSDTEST_CHECK_SYSCALL(mincore(pg0, sz, &mcv[0]));
CHERIBSDTEST_VERIFY2(
(mcv[0] & MINCORE_MODIFIED) != 0, "page 0 modified 1");
CHERIBSDTEST_VERIFY2(
!(mcv[0] & MINCORE_CAPSTORE) == !capstore_on_alloc,
"page 0 capstore 1");

/*
* Write a capability to page 1 and check that it is MODIFIED and
* CAPSTORE regardless of vm.capstore_on_alloc.
*/
*pg1 = (__cheri_tocap void * __capability)pg0;

CHERIBSDTEST_CHECK_SYSCALL(mincore(pg0, sz, &mcv[0]));
CHERIBSDTEST_VERIFY2(
(mcv[1] & MINCORE_MODIFIED) != 0, "page 1 modified 2");
CHERIBSDTEST_VERIFY2(
(mcv[1] & MINCORE_CAPSTORE) != 0, "page 1 capstore 2");

CHERIBSDTEST_CHECK_SYSCALL(munmap(pg0, sz));
cheribsdtest_success();
}
3 changes: 3 additions & 0 deletions sys/mips/include/pmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ void *pmap_kenter_temporary(vm_paddr_t pa, int i);
void pmap_kenter_temporary_free(vm_paddr_t pa);
void pmap_flush_pvcache(vm_page_t m);
int pmap_emulate_modified(pmap_t pmap, vm_offset_t va);
#ifdef CPU_CHERI
int pmap_emulate_capdirty(pmap_t pmap, vm_offset_t va);
#endif
void pmap_page_set_memattr(vm_page_t, vm_memattr_t);
int pmap_change_attr(vm_offset_t, vm_size_t, vm_memattr_t);

Expand Down
15 changes: 11 additions & 4 deletions sys/mips/include/pte.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ pde_page_bound(vm_pointer_t ptr)
*
* Upper bits of a 64 bit PTE:
*
* 63-62 61-----59 58 -- 56 55 54 53
* ---------------------------------------------
* | RG | | PG SZ IDX | MN | W | RO |
* ---------------------------------------------
* 63-62 61-60 59 58 -- 56 55 54 53
* ------------------------------------------------
* | RG | | CRO | PG SZ IDX | MN | W | RO |
* ------------------------------------------------
*
* VM flags managed in software:
*
Expand All @@ -240,6 +240,10 @@ pde_page_bound(vm_pointer_t ptr)
*
* W: Wired. ???
*
* CRO: CHERI-only. Capability read only. Never clear PTE_SCI on this
* entry, and fail attempts to store capabilities to it. The negation
* of PGA_CAPSTORE.
*
* RO: Read only. Never set PTE_D on this page, and don't
* listen to requests to write to it.
*
Expand All @@ -258,6 +262,9 @@ pde_page_bound(vm_pointer_t ptr)
#define PTE_PS_16M ((pt_entry_t)0x30 << TLBLO_SWBITS_SHIFT)
#define PTE_PS_64M ((pt_entry_t)0x38 << TLBLO_SWBITS_SHIFT)
#define PTE_PS_IDX_MASK ((pt_entry_t)0x38 << TLBLO_SWBITS_SHIFT)
#if defined(CPU_CHERI)
#define PTE_CRO ((pt_entry_t)0x40 << TLBLO_SWBITS_SHIFT)
#endif
#endif

#ifdef CPU_CHERI
Expand Down
Loading