|
1 | 1 | //! Functions to flush the translation lookaside buffer (TLB).
|
2 | 2 |
|
3 |
| -use crate::VirtAddr; |
| 3 | +use bit_field::BitField; |
| 4 | + |
| 5 | +use crate::{ |
| 6 | + structures::paging::{page::NotGiantPageSize, Page, PageSize, Size2MiB}, |
| 7 | + VirtAddr, |
| 8 | +}; |
4 | 9 | use core::arch::asm;
|
5 | 10 |
|
6 | 11 | /// Invalidate the given address in the TLB using the `invlpg` instruction.
|
@@ -97,3 +102,57 @@ pub unsafe fn flush_pcid(command: InvPicdCommand) {
|
97 | 102 | asm!("invpcid {0}, [{1}]", in(reg) kind, in(reg) &desc, options(nostack, preserves_flags));
|
98 | 103 | }
|
99 | 104 | }
|
| 105 | + |
| 106 | +/// Invalidates TLB entry(s) with Broadcast. |
| 107 | +/// |
| 108 | +/// # Safety |
| 109 | +/// |
| 110 | +/// This function is unsafe as it requires CPUID.(EAX=8000_0008H, ECX=0H):EBX.INVLPGB |
| 111 | +/// to be 1 and count to be less than or equal to CPUID.(EAX=8000_0008H, ECX=0H):EDX[0..=15]. |
| 112 | +#[inline] |
| 113 | +pub unsafe fn flush_broadcast<S>( |
| 114 | + va_and_count: Option<(Page<S>, u16)>, |
| 115 | + pcid: Option<Pcid>, |
| 116 | + asid: Option<u16>, |
| 117 | + include_global: bool, |
| 118 | + final_translation_only: bool, |
| 119 | + include_nested_translations: bool, |
| 120 | +) where |
| 121 | + S: NotGiantPageSize, |
| 122 | +{ |
| 123 | + let mut rax = 0; |
| 124 | + let mut ecx = 0; |
| 125 | + let mut edx = 0; |
| 126 | + |
| 127 | + if let Some((va, count)) = va_and_count { |
| 128 | + rax.set_bit(0, true); |
| 129 | + rax.set_bits(12.., va.start_address().as_u64().get_bits(12..)); |
| 130 | + |
| 131 | + ecx.set_bits(0..=15, u32::from(count)); |
| 132 | + ecx.set_bit(31, S::SIZE == Size2MiB::SIZE); |
| 133 | + } |
| 134 | + |
| 135 | + if let Some(pcid) = pcid { |
| 136 | + rax.set_bit(1, true); |
| 137 | + edx.set_bits(16..=27, u32::from(pcid.value())); |
| 138 | + } |
| 139 | + |
| 140 | + if let Some(asid) = asid { |
| 141 | + rax.set_bit(2, true); |
| 142 | + edx.set_bits(0..=15, u32::from(asid)); |
| 143 | + } |
| 144 | + |
| 145 | + rax.set_bit(3, include_global); |
| 146 | + rax.set_bit(4, final_translation_only); |
| 147 | + rax.set_bit(5, include_nested_translations); |
| 148 | + |
| 149 | + unsafe { |
| 150 | + asm!( |
| 151 | + "invlpgb", |
| 152 | + in("rax") rax, |
| 153 | + in("ecx") ecx, |
| 154 | + in("edx") edx, |
| 155 | + options(nomem, preserves_flags), |
| 156 | + ); |
| 157 | + } |
| 158 | +} |
0 commit comments