From: Shaoqin Huang <shaoqin.huang@xxxxxxxxx> pKVM already had a mechnism to record page ownership in host EPT, it still needs a place to record page state based on the ownership; the page state is used to identify the exact state of corresponding page: - PKVM_NOPAGE: the page has no mapping in page table (also invalid pte). And under this page state, host EPT is using the pte ignored bits to record owner_id. - PKVM_PAGE_OWNED: the page is owned exclusively by the page-table owner. - PKVM_PAGE_SHARED_OWNED: the page is owned by the page-table owner, but is shared with another entity. - PKVM_PAGE_SHARED_BORROWED: the page is shared with, but not owned by the page-table owner. The bit[56,57] of a EPT page table are ignored in the PTE, so use these two bits as SW bits to record the page state. Signed-off-by: Shaoqin Huang <shaoqin.huang@xxxxxxxxx> --- arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c | 13 ++++++++- arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h | 39 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c index a6554a039468..625c138addfb 100644 --- a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c +++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.c @@ -10,7 +10,9 @@ static u64 pkvm_init_invalid_leaf_owner(pkvm_id owner_id) { - return FIELD_PREP(PKVM_INVALID_PTE_OWNER_MASK, owner_id); + /* the page owned by others also means NOPAGE in page state */ + return FIELD_PREP(PKVM_INVALID_PTE_OWNER_MASK, owner_id) | + FIELD_PREP(PKVM_PAGE_STATE_PROT_MASK, PKVM_NOPAGE); } static int host_ept_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_id) @@ -18,6 +20,15 @@ static int host_ept_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_i u64 annotation = pkvm_init_invalid_leaf_owner(owner_id); int ret; + + /* + * The memory [addr, addr + size) will be unmapped from host ept. At the + * same time, the annotation with a NOPAGE flag will be put in the + * invalid pte that has been unmapped. And the information shows that + * the page has been used by some guest and its id can be read from + * annotation. Also when later these pages are back to host, the annotation + * will be helpful to check the right page transition. + */ ret = pkvm_pgtable_annotate(pkvm_hyp->host_vm.ept, addr, size, annotation); return ret; diff --git a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h index 728de3ac62dd..6b5e0fcbdda0 100644 --- a/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h +++ b/arch/x86/kvm/vmx/pkvm/hyp/mem_protect.h @@ -5,9 +5,48 @@ #ifndef __PKVM_MEM_PROTECT_H__ #define __PKVM_MEM_PROTECT_H__ +/* + * enum pkvm_pgtable_prot - The ignored bits in page-table. + * pkvm will use these ignored bits as software bits to + * identify the page status. + */ +enum pkvm_pgtable_prot { + PKVM_PGTABLE_PROT_SW0 = BIT(56), + PKVM_PGTABLE_PROT_SW1 = BIT(57), +}; + +/* + * Using the ignored bits in page-table as SW bits. + * SW bits 0-1 are used to track the memory ownership state of each page: + * 00: The page has no mapping in page table (also invalid pte). And under + * this page state, host ept is using the pte ignored bits to record owner_id. + * 01: The page is owned exclusively by the page-table owner. + * 10: The page is owned by the page-table owner, but is shared + * with another entity. + * 11: The page is shared with, but not owned by the page-table owner. + */ +enum pkvm_page_state { + PKVM_NOPAGE = 0ULL, + PKVM_PAGE_OWNED = PKVM_PGTABLE_PROT_SW0, + PKVM_PAGE_SHARED_OWNED = PKVM_PGTABLE_PROT_SW1, + PKVM_PAGE_SHARED_BORROWED = PKVM_PGTABLE_PROT_SW0 | + PKVM_PGTABLE_PROT_SW1, +}; + +#define PKVM_PAGE_STATE_PROT_MASK (PKVM_PGTABLE_PROT_SW0 | PKVM_PGTABLE_PROT_SW1) /* use 20 bits[12~31] - not conflict w/ low 12 bits pte prot */ #define PKVM_INVALID_PTE_OWNER_MASK GENMASK(31, 12) +static inline u64 pkvm_mkstate(u64 prot, enum pkvm_page_state state) +{ + return (prot & ~PKVM_PAGE_STATE_PROT_MASK) | state; +} + +static inline enum pkvm_page_state pkvm_getstate(u64 pte) +{ + return pte & PKVM_PAGE_STATE_PROT_MASK; +} + typedef u32 pkvm_id; #define OWNER_ID_HYP 0UL -- 2.25.1