| | 106 | * |
|---|
| | 107 | * |
|---|
| | 108 | * @section sec_pgm_handlers Access Handlers |
|---|
| | 109 | * |
|---|
| | 110 | * Placeholder. |
|---|
| | 111 | * |
|---|
| | 112 | * |
|---|
| | 113 | * @subsection sec_pgm_handlers_virt Virtual Access Handlers |
|---|
| | 114 | * |
|---|
| | 115 | * Placeholder. |
|---|
| | 116 | * |
|---|
| | 117 | * |
|---|
| | 118 | * @subsection sec_pgm_handlers_virt Virtual Access Handlers |
|---|
| | 119 | * |
|---|
| | 120 | * We currently implement three types of virtual access handlers: ALL, WRITE |
|---|
| | 121 | * and HYPERVISOR (WRITE). See PGMVIRTHANDLERTYPE for some more details. |
|---|
| | 122 | * |
|---|
| | 123 | * The HYPERVISOR access handlers is kept in a separate tree since it doesn't apply |
|---|
| | 124 | * to physical pages (PGMTREES::HyperVirtHandlers) and only needs to be consulted in |
|---|
| | 125 | * a special \#PF case. The ALL and WRITE are in the PGMTREES::VirtHandlers tree, the |
|---|
| | 126 | * rest of this section is going to be about these handlers. |
|---|
| | 127 | * |
|---|
| | 128 | * We'll go thru the life cycle of a handler and try make sense of it all, don't know |
|---|
| | 129 | * how successfull this is gonna be... |
|---|
| | 130 | * |
|---|
| | 131 | * 1. A handler is registered thru the PGMR3HandlerVirtualRegister and |
|---|
| | 132 | * PGMHandlerVirtualRegisterEx APIs. We check for conflicting virtual handlers |
|---|
| | 133 | * and create a new node that is inserted into the AVL tree (range key). Then |
|---|
| | 134 | * a full PGM resync is flagged (clear pool, sync cr3, update virtual bit of PGMPAGE). |
|---|
| | 135 | * |
|---|
| | 136 | * 2. The following PGMSyncCR3/SyncCR3 operation will first make invoke HandlerVirtualUpdate. |
|---|
| | 137 | * |
|---|
| | 138 | * 2a. HandlerVirtualUpdate will will lookup all the pages covered by virtual handlers |
|---|
| | 139 | * via the current guest CR3 and update the physical page -> virtual handler |
|---|
| | 140 | * translation. Needless to say, this doesn't exactly scale very well. If any changes |
|---|
| | 141 | * are detected, it will flag a virtual bit update just like we did on registration. |
|---|
| | 142 | * PGMPHYS pages with changes will have their virtual handler state reset to NONE. |
|---|
| | 143 | * |
|---|
| | 144 | * 2b. The virtual bit update process will iterate all the pages covered by all the |
|---|
| | 145 | * virtual handlers and update the PGMPAGE virtual handler state to the max of all |
|---|
| | 146 | * virtual handlers on that page. |
|---|
| | 147 | * |
|---|
| | 148 | * 2c. Back in SyncCR3 we will now flush the entire shadow page cache to make sure |
|---|
| | 149 | * we don't miss any alias mappings of the monitored pages. |
|---|
| | 150 | * |
|---|
| | 151 | * 2d. SyncCR3 will then proceed with syncing the CR3 table. |
|---|
| | 152 | * |
|---|
| | 153 | * 3. \#PF(np,read) on a page in the range. This will cause it to be synced |
|---|
| | 154 | * read-only and resumed if it's a WRITE handler. If it's an ALL handler we |
|---|
| | 155 | * will call the handlers like in the next step. If the physical mapping has |
|---|
| | 156 | * changed we will - some time in the future - perform a handler callback |
|---|
| | 157 | * (optional) and update the physical -> virtual handler cache. |
|---|
| | 158 | * |
|---|
| | 159 | * 4. \#PF(,write) on a page in the range. This will cause the handler to |
|---|
| | 160 | * be invoked. |
|---|
| | 161 | * |
|---|
| | 162 | * 5. The guest invalidates the page and changes the physical backing or |
|---|
| | 163 | * unmaps it. This should cause the invalidation callback to be invoked |
|---|
| | 164 | * (it might not yet be 100% perfect). Exactly what happens next... is |
|---|
| | 165 | * this where we mess up and end up out of sync for a while? |
|---|
| | 166 | * |
|---|
| | 167 | * 6. The handler is deregistered by the client via PGMHandlerVirtualDeregister. |
|---|
| | 168 | * We will then set all PGMPAGEs in the physical -> virtual handler cache for |
|---|
| | 169 | * this handler to NONE and trigger a full PGM resync (basically the same |
|---|
| | 170 | * as int step 1). Which means 2 is executed again. |
|---|
| | 171 | * |
|---|
| | 172 | * |
|---|
| | 173 | * @subsubsection sub_sec_pgm_handler_virt_todo TODOs |
|---|
| | 174 | * |
|---|
| | 175 | * There is a bunch of things that needs to be done to make the virtual handlers |
|---|
| | 176 | * work 100% correctly and work more efficiently. |
|---|
| | 177 | * |
|---|
| | 178 | * The first bit hasn't been implemented yet because it's going to slow the |
|---|
| | 179 | * whole mess down even more, and besides it seems to be working reliably for |
|---|
| | 180 | * our current uses. OTOH, some of the optimizations might end up more or less |
|---|
| | 181 | * implementing the missing bits, so we'll see. |
|---|
| | 182 | * |
|---|
| | 183 | * On the optimization side, the first thing to do is to try avoid unnecessary |
|---|
| | 184 | * cache flushing. Then try team up with the shadowing code to track changes |
|---|
| | 185 | * in mappings by means of access to them (shadow in), updates to shadows pages, |
|---|
| | 186 | * invlpg, and shadow PT discarding (perhaps). |
|---|
| | 187 | * |
|---|
| | 188 | * Some idea that have popped up for optimization for current and new features: |
|---|
| | 189 | * - bitmap indicating where there are virtual handlers installed. |
|---|
| | 190 | * (4KB => 2**20 pages, page 2**12 => covers 32-bit address space 1:1!) |
|---|
| | 191 | * - Further optimize this by min/max (needs min/max avl getters). |
|---|
| | 192 | * - Shadow page table entry bit (if any left)? |
|---|
| | 193 | * |
|---|