xref: /illumos-gate/usr/src/uts/intel/io/vmm/vmm_sol_rvi.c (revision da3b00f42ac14fc3d37aa0e149de7e9832c37b6d)
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