1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 /* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */ 12 13 /* 14 * Copyright 2019 Joyent, Inc. 15 * Copyright 2025 Oxide Computer Company 16 */ 17 18 #include <sys/vmm_gpt_impl.h> 19 20 static inline uint64_t 21 rvi_prot(uint_t prot) 22 { 23 uint64_t bits; 24 25 bits = 0; 26 if ((prot & PROT_WRITE) != 0) 27 bits |= PT_WRITABLE; 28 if ((prot & PROT_EXEC) == 0) 29 bits |= PT_NX; 30 31 return (bits); 32 } 33 34 /* Make sure that PAT indexes line up as expected */ 35 CTASSERT((PAT_DEFAULT_ATTRIBUTE & 0xf) == MTRR_TYPE_WB); 36 CTASSERT(((PAT_DEFAULT_ATTRIBUTE >> 24) & 0xf) == MTRR_TYPE_UC); 37 38 static inline uint64_t 39 rvi_attr_to_pat(uint8_t attr) 40 { 41 if (attr == MTRR_TYPE_UC) 42 return (PT_NOCACHE | PT_WRITETHRU); 43 if (attr == MTRR_TYPE_WB) 44 return (0); 45 46 panic("unexpected memattr %x", attr); 47 } 48 49 static uint64_t 50 rvi_map_table(uint64_t pfn) 51 { 52 const uint64_t paddr = pfn_to_pa(pfn); 53 const uint64_t flags = PT_USER | PT_REF | PT_VALID; 54 const uint64_t pat = rvi_attr_to_pat(MTRR_TYPE_WB); 55 const uint64_t rprot = PT_WRITABLE; 56 return (paddr | flags | pat | rprot); 57 } 58 59 static uint64_t 60 rvi_map_page(uint64_t pfn, uint_t prot, uint8_t attr) 61 { 62 const uint64_t paddr = pfn_to_pa(pfn); 63 const uint64_t flags = PT_USER | PT_REF | PT_VALID; 64 const uint64_t pat = rvi_attr_to_pat(attr); 65 const uint64_t rprot = rvi_prot(prot); 66 return (paddr | flags | pat | rprot); 67 } 68 69 static bool 70 rvi_pte_parse(uint64_t pte, pfn_t *pfnp, uint_t *protp) 71 { 72 if ((pte & PT_VALID) == 0) { 73 return (false); 74 } 75 76 uint_t prot = PROT_READ; 77 if ((pte & PT_NX) == 0) 78 prot |= PROT_EXEC; 79 if ((pte & PT_WRITABLE) != 0) 80 prot |= PROT_WRITE; 81 82 if (pfnp != NULL) { 83 *pfnp = (pte & PT_PADDR) >> PAGESHIFT; 84 } 85 if (protp != NULL) { 86 *protp = prot; 87 } 88 return (true); 89 } 90 91 static uint64_t 92 rvi_get_pmtp(pfn_t root_pfn, bool track_dirty) 93 { 94 return (root_pfn << PAGESHIFT); 95 } 96 97 static bool 98 rvi_hw_ad_supported(void) 99 { 100 return (true); 101 } 102 103 const struct vmm_pte_impl rvi_pte_impl = { 104 .vpi_map_table = rvi_map_table, 105 .vpi_map_page = rvi_map_page, 106 .vpi_pte_parse = rvi_pte_parse, 107 .vpi_bit_accessed = PT_REF, 108 .vpi_bit_dirty = PT_MOD, 109 110 .vpi_get_pmtp = rvi_get_pmtp, 111 .vpi_hw_ad_supported = rvi_hw_ad_supported, 112 }; 113