1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// This file is part of x86_64-xsave. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/x86_64-xsave/master/COPYRIGHT. No part of x86_64-xsave, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
// Copyright © 2019 The developers of x86_64-xsave. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/x86_64-xsave/master/COPYRIGHT.


/// A state component bitmap.
///
/// Can be used to work with the extended control register, `XCR0`.
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct StateComponentBitmap(pub(crate) u64);

impl StateComponentBitmap
{
	/// Read the value of the register `XCR0`.
	///
	/// Will only work if the Operating System has set bit 18 in the register `CR4.OSXSAVE`, otherwise usage will cause an invalid-opcode exception (`#UD`).
	#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "xsave"))]
	pub fn save_from_xcr0() -> Self
	{
		Self(unsafe { _xgetbv(_XCR_XFEATURE_ENABLED_MASK) })
	}

	/// Read the value of the register `XCR0` AND'd with the current value of the `XINUSE` bitmap.
	///
	/// This can be used in conjunction with `xsaveopt` to reduce the amount of data that needs to be saved.
	///
	/// Will only work if the Operating System has set bit 18 in the register `CR4.OSXSAVE`, otherwise usage will cause an invalid-opcode exception (`#UD`).
	#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "xsave", target_feature = "xsaveopt"))]
	pub fn save_from_xcr0_with_init_optimization() -> Self
	{
		Self(unsafe { _xgetbv(1) })
	}

	/// Write this value into the `register`.
	///
	/// Only allowed for kernel-mode code; use in other modes will cause a general-protected fault (`#GP`).
	///
	/// Will only work if the Operating System has set bit 18 in the register `CR4.OSXSAVE`, otherwise usage will cause an invalid-opcode exception (`#UD`).
	#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "xsave"))]
	#[inline(always)]
	pub fn restore_to_xcr0(self)
	{
		unsafe { _xsetbv(_XCR_XFEATURE_ENABLED_MASK, self.0) }
	}

	/// Is present?
	#[inline(always)]
	pub fn set_is_present(&mut self, state_component: StateComponent)
	{
		let bit = state_component.bit();

		self.0 |= 1 << (bit as u64);
	}

	/// Is present?
	#[inline(always)]
	pub fn is_present(self, state_component: StateComponent) -> bool
	{
		self.bit_set(state_component.bit())
	}

	#[inline(always)]
	fn bit_set(self, bit: u8) -> bool
	{
		self.0 & (1 << (bit as u64)) != 0
	}

	#[inline(always)]
	fn bits_are_zero(self, mask: u64) -> bool
	{
		(self.0 & mask) == 0
	}
}