hypervisor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d3a9c9ae2e397be3f6b354a4adb17e8922b175061a398b2500f0d38fffcaadaa
4
+ data.tar.gz: 4c33c8bd868d7f27937c0335f9a3168555ed9d5929a50baa10dc5b1106f705fd
5
+ SHA512:
6
+ metadata.gz: ce031fd0405934eeb2910c9a55d33580e4538f92458068db1221a574b1231d62e2ed790a7f7cb2186477050c1802e50fca1f97367843d06af5cc4c35f1dd47b7
7
+ data.tar.gz: 70c68c9640c6631819f1df051fc101568df6f912f5138bb438b4ebf32ae7582dae90481d938f1905e03379624efdb1b0db6f1a9b5f0ccaecfd068b5455a38dbd
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ before_install: gem install bundler -v 1.16.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in hv.gemspec
6
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Aurora
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # Hypervisor
2
+
3
+ `hypervisor` is a gem that provides Ruby code access to the hypervisor on macOS.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'hv'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install hv
20
+
21
+ ## Usage
22
+
23
+ There's `examples/dos` that is a script that implements the start of a DOS kernel in Ruby.
24
+
25
+ ## Contributing
26
+
27
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rawrasaur/hvpervisor.
28
+
29
+ ## License
30
+
31
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hv"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,226 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "hypervisor"
4
+
5
+ MEMORY_SIZE = 1 << 20 # 1 MB
6
+
7
+ class DOSKernel
8
+ class Stop < StandardError
9
+ attr_reader :return_value
10
+
11
+ def initialize(return_value)
12
+ @return_value = return_value
13
+
14
+ super("Exiting DOS")
15
+ end
16
+ end
17
+
18
+ def initialize(memory, argv)
19
+ @memory = memory
20
+ @argv = argv
21
+ @dta = 0
22
+
23
+ @fds = {
24
+ 0 => $stdin,
25
+ 1 => $stdout,
26
+ 2 => $stderr
27
+ }
28
+
29
+ @next_fd = 2
30
+
31
+ @memory.put_bytes(0x00, [0xcd, 0x20].pack("c*"))
32
+ @memory.put_bytes(0x50, [0xcd, 0x21, 0xcb].pack("c*"))
33
+ @memory.put_bytes(0x5C, [0x01, 0x20].pack("c*"))
34
+
35
+ argv = argv.map { |x| " #{x}" }.join('')
36
+
37
+ @memory.put_bytes(0x80, [argv.bytesize, argv, 0x0d].pack("cA*c"))
38
+ end
39
+
40
+ def dispatch(cpu, int)
41
+ case int
42
+ when 0x20
43
+ interrupt_0x20(cpu)
44
+ when 0x21
45
+ interrupt_0x21(cpu)
46
+ else
47
+ raise "Unknown interrupt: #{int}"
48
+ end
49
+ end
50
+
51
+ private def allocate_fd
52
+ @next_fd += 1
53
+ end
54
+
55
+ private def interrupt_0x20(cpu)
56
+ raise "Unsupported: int 0x20 / #{cpu.ah.to_s(16)}"
57
+ end
58
+
59
+ private def interrupt_0x21(cpu)
60
+ case cpu.ah
61
+ when 0x1a # set dta
62
+ @dta = cpu.dx
63
+ when 0x30 # version
64
+ cpu.write_register(Hypervisor::X86_RAX, 0x0700)
65
+ when 0x3d # open
66
+ # TODO: Don't ignore OFLAG
67
+ fd = File.open(read_string(cpu.ds, cpu.dx))
68
+ dos_fd = allocate_fd
69
+
70
+ @fds[dos_fd] = fd
71
+
72
+ cpu.ax = dos_fd
73
+ cpu.cf = 0
74
+ when 0x3f # read
75
+ fd = @fds.fetch(cpu.bx)
76
+ data = fd.read(cpu.cx)
77
+
78
+ if data
79
+ write_segment(cpu.ds, cpu.dx, data)
80
+
81
+ cpu.ax = data.bytesize
82
+ cpu.cf = 0
83
+ else
84
+ cpu.ax = 0
85
+ cpu.cf = 1
86
+ end
87
+ when 0x40 # write
88
+ fd = @fds.fetch(cpu.bx)
89
+
90
+ cpu.ax = fd.write(read_segment(cpu.ds, cpu.dx, cpu.cx))
91
+ cpu.cf = 0
92
+ when 0x42 # lseek
93
+ fd = @fds.fetch(cpu.bx)
94
+
95
+ fd.seek(cpu.cx << 16 | cpu.dx, cpu.al)
96
+ when 0x4c # exit
97
+ raise Stop.new(cpu.al)
98
+ else
99
+ raise "Unsupported: int 0x21 / #{cpu.ah.to_s(16)}"
100
+ end
101
+ end
102
+
103
+ def read_segment(s, x, length)
104
+ @memory.get_bytes((s << 4) + x, length)
105
+ end
106
+
107
+ def read_string(s, x)
108
+ @memory.get_string((s << 4) + x)
109
+ end
110
+
111
+ def write_segment(s, x, value)
112
+ @memory.put_bytes((s << 4) + x, value)
113
+ end
114
+ end
115
+
116
+ def cap(cap, ctrl)
117
+ (ctrl | (cap & 0xffffffff)) & (cap >> 32)
118
+ end
119
+
120
+ Hypervisor.create
121
+
122
+ memory = Hypervisor.allocate(MEMORY_SIZE)
123
+ memory.put_bytes(0x100, File.read(ARGV[0]))
124
+
125
+ kernel = DOSKernel.new(memory, ARGV[1 .. -1])
126
+
127
+ Hypervisor.map(memory, 0, MEMORY_SIZE, Hypervisor::MEMORY_READ | Hypervisor::MEMORY_WRITE | Hypervisor::MEMORY_EXEC)
128
+
129
+ cpu = Hypervisor::VCPU.new
130
+ cpu.write_vmcs(Hypervisor::VMX_CAP_PINBASED, cap(Hypervisor.read_capability(Hypervisor::VMX_CAP_PINBASED), 0))
131
+ cpu.write_vmcs(Hypervisor::VMX_CAP_PROCBASED, cap(Hypervisor.read_capability(Hypervisor::VMX_CAP_PROCBASED), Hypervisor::CPU_BASED_HLT | Hypervisor::CPU_BASED_CR8_LOAD | Hypervisor::CPU_BASED_CR8_STORE))
132
+ cpu.write_vmcs(Hypervisor::VMX_CAP_PROCBASED2, cap(Hypervisor.read_capability(Hypervisor::VMX_CAP_PROCBASED2), 0))
133
+ cpu.write_vmcs(Hypervisor::VMX_CAP_ENTRY, cap(Hypervisor.read_capability(Hypervisor::VMX_CAP_ENTRY), 0))
134
+ cpu.write_vmcs(Hypervisor::VMX_CAP_PREEMPTION_TIMER, cap(Hypervisor.read_capability(Hypervisor::VMX_CAP_PREEMPTION_TIMER), 0))
135
+
136
+ cpu.write_vmcs(Hypervisor::VMCS_CTRL_EXC_BITMAP, 0xffffffff)
137
+ cpu.write_vmcs(Hypervisor::VMCS_CTRL_CR0_MASK, 0x60000000)
138
+ cpu.write_vmcs(Hypervisor::VMCS_CTRL_CR0_SHADOW, 0)
139
+ cpu.write_vmcs(Hypervisor::VMCS_CTRL_CR4_MASK, 0)
140
+ cpu.write_vmcs(Hypervisor::VMCS_CTRL_CR4_SHADOW, 0)
141
+
142
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CS, 0)
143
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CS_LIMIT, 0xffff)
144
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CS_AR, 0x9b)
145
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CS_BASE, 0)
146
+
147
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_DS, 0)
148
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_DS_LIMIT, 0xffff)
149
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_DS_AR, 0x93)
150
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_DS_BASE, 0)
151
+
152
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_ES, 0)
153
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_ES_LIMIT, 0xffff)
154
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_ES_AR, 0x93)
155
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_ES_BASE, 0)
156
+
157
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_FS, 0)
158
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_FS_LIMIT, 0xffff)
159
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_FS_AR, 0x93)
160
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_FS_BASE, 0)
161
+
162
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_GS, 0)
163
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_GS_LIMIT, 0xffff)
164
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_GS_AR, 0x93)
165
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_GS_BASE, 0)
166
+
167
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_SS, 0)
168
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_SS_LIMIT, 0xffff)
169
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_SS_AR, 0x93)
170
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_SS_BASE, 0)
171
+
172
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_LDTR, 0)
173
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_LDTR_LIMIT, 0)
174
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_LDTR_AR, 0x10000)
175
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_LDTR_BASE, 0)
176
+
177
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_TR, 0)
178
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_TR_LIMIT, 0)
179
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_TR_AR, 0x83)
180
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_TR_BASE, 0)
181
+
182
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_GDTR_LIMIT, 0)
183
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_GDTR_BASE, 0)
184
+
185
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_IDTR_LIMIT, 0)
186
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_IDTR_BASE, 0)
187
+
188
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CR0, 0x20)
189
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CR3, 0x0)
190
+ cpu.write_vmcs(Hypervisor::VMCS_GUEST_CR4, 0x2000)
191
+
192
+ cpu.write_register(Hypervisor::X86_RIP, 0x100)
193
+ cpu.write_register(Hypervisor::X86_RFLAGS, 0x2)
194
+ cpu.write_register(Hypervisor::X86_RSP, 0x0)
195
+
196
+ return_value = -1
197
+
198
+ loop do
199
+ cpu.run
200
+
201
+ case cpu.read_vmcs(Hypervisor::VMCS_RO_EXIT_REASON)
202
+ when Hypervisor::VMX_REASON_EPT_VIOLATION, Hypervisor::VMX_REASON_IRQ
203
+ next
204
+ when Hypervisor::VMX_REASON_HLT
205
+ break
206
+ when Hypervisor::VMX_REASON_EXC_NMI
207
+ n = cpu.read_vmcs(Hypervisor::VMCS_RO_IDT_VECTOR_INFO) & 0xff
208
+
209
+ begin
210
+ kernel.dispatch(cpu, n)
211
+ cpu.write_register(Hypervisor::X86_RIP, cpu.read_register(Hypervisor::X86_RIP) + 2)
212
+ rescue DOSKernel::Stop => e
213
+ return_value = e.return_value
214
+ break
215
+ end
216
+ else
217
+ $stderr.puts("ERROR: #{cpu.read_vmcs(Hypervisor::VMCS_RO_EXIT_REASON)}")
218
+ break
219
+ end
220
+ end
221
+
222
+ cpu.destroy!
223
+
224
+ Hypervisor.destroy
225
+
226
+ exit(return_value)
@@ -0,0 +1,30 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require "hypervisor/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hypervisor"
8
+ spec.version = Hypervisor::VERSION
9
+ spec.authors = ["Aurora"]
10
+ spec.email = ["aurora@aventine.se"]
11
+
12
+ spec.summary = %q{Hypervisor for macOS}
13
+ spec.description = %q{A wrapper for Hypervisor.framework on macOS}
14
+ spec.homepage = "https://github.com/rawrasaur/hvpervisor"
15
+ spec.license = "MIT"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.16"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ spec.add_runtime_dependency "ffi", "~> 1.9"
30
+ end
@@ -0,0 +1,44 @@
1
+ require "hypervisor/version"
2
+ require "hypervisor/constants"
3
+ require "hypervisor/framework"
4
+ require "hypervisor/vcpu"
5
+
6
+ require 'ffi'
7
+
8
+ module Hypervisor
9
+ def self.allocate(n, &block)
10
+ FFI::AutoPointer.new(Hypervisor::Framework.valloc(n), Hypervisor::Framework.method(:free), &block)
11
+ end
12
+
13
+ def self.create(options = VM_DEFAULT)
14
+ Framework.return_t(Framework.hv_vm_create(options))
15
+ end
16
+
17
+ def self.destroy
18
+ Framework.return_t(Framework.hv_vm_destroy)
19
+ end
20
+
21
+ def self.map(uva, gpa, size, flags)
22
+ Framework.return_t(Framework.hv_vm_map(uva, gpa, size, flags))
23
+ end
24
+
25
+ def self.unmap(gpa, size)
26
+ Framework.return_t(Framework.hv_vm_unmap(gpa, size))
27
+ end
28
+
29
+ def self.protect(gpa, size, flags)
30
+ Framework.return_t(Framework.hv_vm_protect(gpa, size, flags))
31
+ end
32
+
33
+ def self.sync_tsc(tsc)
34
+ Framework.return_t(Framework.hv_vm_sync_tsc(tsc))
35
+ end
36
+
37
+ def self.read_capability(field)
38
+ FFI::MemoryPointer.new(:uint64_t, 1) do |value|
39
+ Framework.return_t(Framework.hv_vmx_read_capability(field, value))
40
+
41
+ return value.get_uint64(0)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,384 @@
1
+ module Hypervisor
2
+ # hv_error.h
3
+
4
+ SUCCESS = 0
5
+ ERROR = 0xfae94001
6
+ BUSY = 0xfae94002
7
+ BAD_ARGUMENT = 0xfae94003
8
+ NO_RESOURCES = 0xfae94005
9
+ NO_DEVICE = 0xfae94006
10
+ UNSUPPORTED = 0xfae9400f
11
+
12
+ # hv_types.h
13
+
14
+ VM_DEFAULT = 0
15
+ VM_SPECIFY_MITIGATIONS = 1 << 0
16
+ VM_MITIGATION_A_ENABLE = 1 << 1
17
+ VM_MITIGATION_B_ENABLE = 1 << 2
18
+ VM_MITIGATION_C_ENABLE = 1 << 3
19
+ VM_MITIGATION_D_ENABLE = 1 << 4
20
+
21
+ VCPU_DEFAULT = 0
22
+
23
+ MEMORY_READ = 1 << 0
24
+ MEMORY_WRITE = 1 << 1
25
+ MEMORY_EXEC = 1 << 2
26
+
27
+ # hv_arch_x86.h
28
+
29
+ X86_RIP = 0
30
+ X86_RFLAGS = 1
31
+ X86_RAX = 2
32
+ X86_RCX = 3
33
+ X86_RDX = 4
34
+ X86_RBX = 5
35
+ X86_RSI = 6
36
+ X86_RDI = 7
37
+ X86_RSP = 8
38
+ X86_RBP = 9
39
+ X86_R8 = 10
40
+ X86_R9 = 11
41
+ X86_R10 = 12
42
+ X86_R11 = 13
43
+ X86_R12 = 14
44
+ X86_R13 = 15
45
+ X86_R14 = 16
46
+ X86_R15 = 17
47
+ X86_CS = 18
48
+ X86_SS = 19
49
+ X86_DS = 20
50
+ X86_ES = 21
51
+ X86_FS = 22
52
+ X86_GS = 23
53
+ X86_IDT_BASE = 24
54
+ X86_IDT_LIMIT = 25
55
+ X86_GDT_BASE = 26
56
+ X86_GDT_LIMIT = 27
57
+ X86_LDTR = 28
58
+ X86_LDT_BASE = 29
59
+ X86_LDT_LIMIT = 30
60
+ X86_LDT_AR = 31
61
+ X86_TR = 32
62
+ X86_TSS_BASE = 33
63
+ X86_TSS_LIMIT = 34
64
+ X86_TSS_AR = 35
65
+ X86_CR0 = 36
66
+ X86_CR1 = 37
67
+ X86_CR2 = 38
68
+ X86_CR3 = 39
69
+ X86_CR4 = 40
70
+ X86_DR0 = 41
71
+ X86_DR1 = 42
72
+ X86_DR2 = 43
73
+ X86_DR3 = 44
74
+ X86_DR4 = 45
75
+ X86_DR5 = 46
76
+ X86_DR6 = 47
77
+ X86_DR7 = 48
78
+ X86_TPR = 49
79
+ X86_XCR0 = 50
80
+
81
+ # hv_vmx.h
82
+
83
+ VMX_CAP_PINBASED = 0
84
+ VMX_CAP_PROCBASED = 1
85
+ VMX_CAP_PROCBASED2 = 2
86
+ VMX_CAP_ENTRY = 3
87
+ VMX_CAP_EXIT = 4
88
+ VMX_CAP_PREEMPTION_TIMER = 32
89
+
90
+ # hv_arch_vmx.h
91
+
92
+ VMCS_VPID = 0x00000000
93
+ VMCS_CTRL_POSTED_INT_N_VECTOR = 0x00000002
94
+ VMCS_CTRL_EPTP_INDEX = 0x00000004
95
+ VMCS_GUEST_ES = 0x00000800
96
+ VMCS_GUEST_CS = 0x00000802
97
+ VMCS_GUEST_SS = 0x00000804
98
+ VMCS_GUEST_DS = 0x00000806
99
+ VMCS_GUEST_FS = 0x00000808
100
+ VMCS_GUEST_GS = 0x0000080a
101
+ VMCS_GUEST_LDTR = 0x0000080c
102
+ VMCS_GUEST_TR = 0x0000080e
103
+ VMCS_GUEST_INT_STATUS = 0x00000810
104
+ VMCS_HOST_ES = 0x00000c00
105
+ VMCS_HOST_CS = 0x00000c02
106
+ VMCS_HOST_SS = 0x00000c04
107
+ VMCS_HOST_DS = 0x00000c06
108
+ VMCS_HOST_FS = 0x00000c08
109
+ VMCS_HOST_GS = 0x00000c0a
110
+ VMCS_HOST_TR = 0x00000c0c
111
+ VMCS_CTRL_IO_BITMAP_A = 0x00002000
112
+ VMCS_CTRL_IO_BITMAP_B = 0x00002002
113
+ VMCS_CTRL_MSR_BITMAPS = 0x00002004
114
+ VMCS_CTRL_VMEXIT_MSR_STORE_ADDR = 0x00002006
115
+ VMCS_CTRL_VMEXIT_MSR_LOAD_ADDR = 0x00002008
116
+ VMCS_CTRL_VMENTRY_MSR_LOAD_ADDR = 0x0000200a
117
+ VMCS_CTRL_EXECUTIVE_VMCS_PTR = 0x0000200c
118
+ VMCS_CTRL_TSC_OFFSET = 0x00002010
119
+ VMCS_CTRL_VIRTUAL_APIC = 0x00002012
120
+ VMCS_CTRL_APIC_ACCESS = 0x00002014
121
+ VMCS_CTRL_POSTED_INT_DESC_ADDR = 0x00002016
122
+ VMCS_CTRL_VMFUNC_CTRL = 0x00002018
123
+ VMCS_CTRL_EPTP = 0x0000201a
124
+ VMCS_CTRL_EOI_EXIT_BITMAP_0 = 0x0000201c
125
+ VMCS_CTRL_EOI_EXIT_BITMAP_1 = 0x0000201e
126
+ VMCS_CTRL_EOI_EXIT_BITMAP_2 = 0x00002020
127
+ VMCS_CTRL_EOI_EXIT_BITMAP_3 = 0x00002022
128
+ VMCS_CTRL_EPTP_LIST_ADDR = 0x00002024
129
+ VMCS_CTRL_VMREAD_BITMAP_ADDR = 0x00002026
130
+ VMCS_CTRL_VMWRITE_BITMAP_ADDR = 0x00002028
131
+ VMCS_CTRL_VIRT_EXC_INFO_ADDR = 0x0000202a
132
+ VMCS_CTRL_XSS_EXITING_BITMAP = 0x0000202c
133
+ VMCS_GUEST_PHYSICAL_ADDRESS = 0x00002400
134
+ VMCS_GUEST_LINK_POINTER = 0x00002800
135
+ VMCS_GUEST_IA32_DEBUGCTL = 0x00002802
136
+ VMCS_GUEST_IA32_PAT = 0x00002804
137
+ VMCS_GUEST_IA32_EFER = 0x00002806
138
+ VMCS_GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808
139
+ VMCS_GUEST_PDPTE0 = 0x0000280a
140
+ VMCS_GUEST_PDPTE1 = 0x0000280c
141
+ VMCS_GUEST_PDPTE2 = 0x0000280e
142
+ VMCS_GUEST_PDPTE3 = 0x00002810
143
+ VMCS_HOST_IA32_PAT = 0x00002c00
144
+ VMCS_HOST_IA32_EFER = 0x00002c02
145
+ VMCS_HOST_IA32_PERF_GLOBAL_CTRL = 0x00002c04
146
+ VMCS_CTRL_PIN_BASED = 0x00004000
147
+ VMCS_CTRL_CPU_BASED = 0x00004002
148
+ VMCS_CTRL_EXC_BITMAP = 0x00004004
149
+ VMCS_CTRL_PF_ERROR_MASK = 0x00004006
150
+ VMCS_CTRL_PF_ERROR_MATCH = 0x00004008
151
+ VMCS_CTRL_CR3_COUNT = 0x0000400a
152
+ VMCS_CTRL_VMEXIT_CONTROLS = 0x0000400c
153
+ VMCS_CTRL_VMEXIT_MSR_STORE_COUNT = 0x0000400e
154
+ VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT = 0x00004010
155
+ VMCS_CTRL_VMENTRY_CONTROLS = 0x00004012
156
+ VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT = 0x00004014
157
+ VMCS_CTRL_VMENTRY_IRQ_INFO = 0x00004016
158
+ VMCS_CTRL_VMENTRY_EXC_ERROR = 0x00004018
159
+ VMCS_CTRL_VMENTRY_INSTR_LEN = 0x0000401a
160
+ VMCS_CTRL_TPR_THRESHOLD = 0x0000401c
161
+ VMCS_CTRL_CPU_BASED2 = 0x0000401e
162
+ VMCS_CTRL_PLE_GAP = 0x00004020
163
+ VMCS_CTRL_PLE_WINDOW = 0x00004022
164
+ VMCS_RO_INSTR_ERROR = 0x00004400
165
+ VMCS_RO_EXIT_REASON = 0x00004402
166
+ VMCS_RO_VMEXIT_IRQ_INFO = 0x00004404
167
+ VMCS_RO_VMEXIT_IRQ_ERROR = 0x00004406
168
+ VMCS_RO_IDT_VECTOR_INFO = 0x00004408
169
+ VMCS_RO_IDT_VECTOR_ERROR = 0x0000440a
170
+ VMCS_RO_VMEXIT_INSTR_LEN = 0x0000440c
171
+ VMCS_RO_VMX_INSTR_INFO = 0x0000440e
172
+ VMCS_GUEST_ES_LIMIT = 0x00004800
173
+ VMCS_GUEST_CS_LIMIT = 0x00004802
174
+ VMCS_GUEST_SS_LIMIT = 0x00004804
175
+ VMCS_GUEST_DS_LIMIT = 0x00004806
176
+ VMCS_GUEST_FS_LIMIT = 0x00004808
177
+ VMCS_GUEST_GS_LIMIT = 0x0000480a
178
+ VMCS_GUEST_LDTR_LIMIT = 0x0000480c
179
+ VMCS_GUEST_TR_LIMIT = 0x0000480e
180
+ VMCS_GUEST_GDTR_LIMIT = 0x00004810
181
+ VMCS_GUEST_IDTR_LIMIT = 0x00004812
182
+ VMCS_GUEST_ES_AR = 0x00004814
183
+ VMCS_GUEST_CS_AR = 0x00004816
184
+ VMCS_GUEST_SS_AR = 0x00004818
185
+ VMCS_GUEST_DS_AR = 0x0000481a
186
+ VMCS_GUEST_FS_AR = 0x0000481c
187
+ VMCS_GUEST_GS_AR = 0x0000481e
188
+ VMCS_GUEST_LDTR_AR = 0x00004820
189
+ VMCS_GUEST_TR_AR = 0x00004822
190
+ VMCS_GUEST_IGNORE_IRQ = 0x00004824
191
+ VMCS_GUEST_ACTIVITY_STATE = 0x00004826
192
+ VMCS_GUEST_SMBASE = 0x00004828
193
+ VMCS_GUEST_IA32_SYSENTER_CS = 0x0000482a
194
+ VMCS_GUEST_VMX_TIMER_VALUE = 0x0000482e
195
+ VMCS_HOST_IA32_SYSENTER_CS = 0x00004c00
196
+ VMCS_CTRL_CR0_MASK = 0x00006000
197
+ VMCS_CTRL_CR4_MASK = 0x00006002
198
+ VMCS_CTRL_CR0_SHADOW = 0x00006004
199
+ VMCS_CTRL_CR4_SHADOW = 0x00006006
200
+ VMCS_CTRL_CR3_VALUE0 = 0x00006008
201
+ VMCS_CTRL_CR3_VALUE1 = 0x0000600a
202
+ VMCS_CTRL_CR3_VALUE2 = 0x0000600c
203
+ VMCS_CTRL_CR3_VALUE3 = 0x0000600e
204
+ VMCS_RO_EXIT_QUALIFIC = 0x00006400
205
+ VMCS_RO_IO_RCX = 0x00006402
206
+ VMCS_RO_IO_RSI = 0x00006404
207
+ VMCS_RO_IO_RDI = 0x00006406
208
+ VMCS_RO_IO_RIP = 0x00006408
209
+ VMCS_RO_GUEST_LIN_ADDR = 0x0000640a
210
+ VMCS_GUEST_CR0 = 0x00006800
211
+ VMCS_GUEST_CR3 = 0x00006802
212
+ VMCS_GUEST_CR4 = 0x00006804
213
+ VMCS_GUEST_ES_BASE = 0x00006806
214
+ VMCS_GUEST_CS_BASE = 0x00006808
215
+ VMCS_GUEST_SS_BASE = 0x0000680a
216
+ VMCS_GUEST_DS_BASE = 0x0000680c
217
+ VMCS_GUEST_FS_BASE = 0x0000680e
218
+ VMCS_GUEST_GS_BASE = 0x00006810
219
+ VMCS_GUEST_LDTR_BASE = 0x00006812
220
+ VMCS_GUEST_TR_BASE = 0x00006814
221
+ VMCS_GUEST_GDTR_BASE = 0x00006816
222
+ VMCS_GUEST_IDTR_BASE = 0x00006818
223
+ VMCS_GUEST_DR7 = 0x0000681a
224
+ VMCS_GUEST_RSP = 0x0000681c
225
+ VMCS_GUEST_RIP = 0x0000681e
226
+ VMCS_GUEST_RFLAGS = 0x00006820
227
+ VMCS_GUEST_DEBUG_EXC = 0x00006822
228
+ VMCS_GUEST_SYSENTER_ESP = 0x00006824
229
+ VMCS_GUEST_SYSENTER_EIP = 0x00006826
230
+ VMCS_HOST_CR0 = 0x00006c00
231
+ VMCS_HOST_CR3 = 0x00006c02
232
+ VMCS_HOST_CR4 = 0x00006c04
233
+ VMCS_HOST_FS_BASE = 0x00006c06
234
+ VMCS_HOST_GS_BASE = 0x00006c08
235
+ VMCS_HOST_TR_BASE = 0x00006c0a
236
+ VMCS_HOST_GDTR_BASE = 0x00006c0c
237
+ VMCS_HOST_IDTR_BASE = 0x00006c0e
238
+ VMCS_HOST_IA32_SYSENTER_ESP = 0x00006c10
239
+ VMCS_HOST_IA32_SYSENTER_EIP = 0x00006c12
240
+ VMCS_HOST_RSP = 0x00006c14
241
+ VMCS_HOST_RIP = 0x00006c16
242
+ VMCS_MAX = 0x00006c18
243
+
244
+ VMX_BASIC_TRUE_CTLS = 1 << 55
245
+
246
+ PIN_BASED_INTR = 1 << 0
247
+ PIN_BASED_NMI = 1 << 3
248
+ PIN_BASED_VIRTUAL_NMI = 1 << 5
249
+ PIN_BASED_PREEMPTION_TIMER = 1 << 6
250
+ PIN_BASED_POSTED_INTR = 1 << 7
251
+
252
+ CPU_BASED_IRQ_WND = 1 << 2
253
+ CPU_BASED_TSC_OFFSET = 1 << 3
254
+ CPU_BASED_HLT = 1 << 7
255
+ CPU_BASED_INVLPG = 1 << 9
256
+ CPU_BASED_MWAIT = 1 << 10
257
+ CPU_BASED_RDPMC = 1 << 11
258
+ CPU_BASED_RDTSC = 1 << 12
259
+ CPU_BASED_CR3_LOAD = 1 << 15
260
+ CPU_BASED_CR3_STORE = 1 << 16
261
+ CPU_BASED_CR8_LOAD = 1 << 19
262
+ CPU_BASED_CR8_STORE = 1 << 20
263
+ CPU_BASED_TPR_SHADOW = 1 << 21
264
+ CPU_BASED_VIRTUAL_NMI_WND = 1 << 22
265
+ CPU_BASED_MOV_DR = 1 << 23
266
+ CPU_BASED_UNCOND_IO = 1 << 24
267
+ CPU_BASED_IO_BITMAPS = 1 << 25
268
+ CPU_BASED_MTF = 1 << 27
269
+ CPU_BASED_MSR_BITMAPS = 1 << 28
270
+ CPU_BASED_MONITOR = 1 << 29
271
+ CPU_BASED_PAUSE = 1 << 30
272
+ CPU_BASED_SECONDARY_CTLS = 1 << 31
273
+
274
+ CPU_BASED2_VIRTUAL_APIC = 1 << 0
275
+ CPU_BASED2_EPT = 1 << 1
276
+ CPU_BASED2_DESC_TABLE = 1 << 2
277
+ CPU_BASED2_RDTSCP = 1 << 3
278
+ CPU_BASED2_X2APIC = 1 << 4
279
+ CPU_BASED2_VPID = 1 << 5
280
+ CPU_BASED2_WBINVD = 1 << 6
281
+ CPU_BASED2_UNRESTRICTED = 1 << 7
282
+ CPU_BASED2_APIC_REG_VIRT = 1 << 8
283
+ CPU_BASED2_VIRT_INTR_DELIVERY = 1 << 9
284
+ CPU_BASED2_PAUSE_LOOP = 1 << 10
285
+ CPU_BASED2_RDRAND = 1 << 11
286
+ CPU_BASED2_INVPCID = 1 << 12
287
+ CPU_BASED2_VMFUNC = 1 << 13
288
+ CPU_BASED2_VMCS_SHADOW = 1 << 14
289
+ CPU_BASED2_RDSEED = 1 << 16
290
+ CPU_BASED2_EPT_VE = 1 << 18
291
+ CPU_BASED2_XSAVES_XRSTORS = 1 << 20
292
+
293
+ VMX_EPT_VPID_SUPPORT_AD = 1 << 21
294
+ VMX_EPT_VPID_SUPPORT_EXONLY = 1 << 0
295
+
296
+ VMEXIT_SAVE_DBG_CONTROLS = 1 << 2
297
+ VMEXIT_HOST_IA32E = 1 << 9
298
+ VMEXIT_LOAD_IA32_PERF_GLOBAL_CTRL = 1 << 12
299
+ VMEXIT_ACK_INTR = 1 << 15
300
+ VMEXIT_SAVE_IA32_PAT = 1 << 18
301
+ VMEXIT_LOAD_IA32_PAT = 1 << 19
302
+ VMEXIT_SAVE_EFER = 1 << 20
303
+ VMEXIT_LOAD_EFER = 1 << 21
304
+ VMEXIT_SAVE_VMX_TIMER = 1 << 22
305
+
306
+ VMENTRY_LOAD_DBG_CONTROLS = 1 << 2
307
+ VMENTRY_GUEST_IA32E = 1 << 9
308
+ VMENTRY_SMM = 1 << 10
309
+ VMENTRY_DEACTIVATE_DUAL_MONITOR = 1 << 11
310
+ VMENTRY_LOAD_IA32_PERF_GLOBAL_CTRL = 1 << 13
311
+ VMENTRY_LOAD_IA32_PAT = 1 << 14
312
+ VMENTRY_LOAD_EFER = 1 << 15
313
+
314
+ VMX_REASON_EXC_NMI = 0
315
+ VMX_REASON_IRQ = 1
316
+ VMX_REASON_TRIPLE_FAULT = 2
317
+ VMX_REASON_INIT = 3
318
+ VMX_REASON_SIPI = 4
319
+ VMX_REASON_IO_SMI = 5
320
+ VMX_REASON_OTHER_SMI = 6
321
+ VMX_REASON_IRQ_WND = 7
322
+ VMX_REASON_VIRTUAL_NMI_WND = 8
323
+ VMX_REASON_TASK = 9
324
+ VMX_REASON_CPUID = 10
325
+ VMX_REASON_GETSEC = 11
326
+ VMX_REASON_HLT = 12
327
+ VMX_REASON_INVD = 13
328
+ VMX_REASON_INVLPG = 14
329
+ VMX_REASON_RDPMC = 15
330
+ VMX_REASON_RDTSC = 16
331
+ VMX_REASON_RSM = 17
332
+ VMX_REASON_VMCALL = 18
333
+ VMX_REASON_VMCLEAR = 19
334
+ VMX_REASON_VMLAUNCH = 20
335
+ VMX_REASON_VMPTRLD = 21
336
+ VMX_REASON_VMPTRST = 22
337
+ VMX_REASON_VMREAD = 23
338
+ VMX_REASON_VMRESUME = 24
339
+ VMX_REASON_VMWRITE = 25
340
+ VMX_REASON_VMOFF = 26
341
+ VMX_REASON_VMON = 27
342
+ VMX_REASON_MOV_CR = 28
343
+ VMX_REASON_MOV_DR = 29
344
+ VMX_REASON_IO = 30
345
+ VMX_REASON_RDMSR = 31
346
+ VMX_REASON_WRMSR = 32
347
+ VMX_REASON_VMENTRY_GUEST = 33
348
+ VMX_REASON_VMENTRY_MSR = 34
349
+ VMX_REASON_MWAIT = 36
350
+ VMX_REASON_MTF = 37
351
+ VMX_REASON_MONITOR = 39
352
+ VMX_REASON_PAUSE = 40
353
+ VMX_REASON_VMENTRY_MC = 41
354
+ VMX_REASON_TPR_THRESHOLD = 43
355
+ VMX_REASON_APIC_ACCESS = 44
356
+ VMX_REASON_VIRTUALIZED_EOI = 45
357
+ VMX_REASON_GDTR_IDTR = 46
358
+ VMX_REASON_LDTR_TR = 47
359
+ VMX_REASON_EPT_VIOLATION = 48
360
+ VMX_REASON_EPT_MISCONFIG = 49
361
+ VMX_REASON_EPT_INVEPT = 50
362
+ VMX_REASON_RDTSCP = 51
363
+ VMX_REASON_VMX_TIMER_EXPIRED = 52
364
+ VMX_REASON_INVVPID = 53
365
+ VMX_REASON_WBINVD = 54
366
+ VMX_REASON_XSETBV = 55
367
+ VMX_REASON_APIC_WRITE = 56
368
+ VMX_REASON_RDRAND = 57
369
+ VMX_REASON_INVPCID = 58
370
+ VMX_REASON_VMFUNC = 59
371
+ VMX_REASON_RDSEED = 61
372
+ VMX_REASON_XSAVES = 63
373
+ VMX_REASON_XRSTORS = 64
374
+
375
+ IRQ_INFO_EXT_IRQ = 0 << 8
376
+ IRQ_INFO_NMI = 2 << 8
377
+ IRQ_INFO_HARD_EXC = 3 << 8
378
+ IRQ_INFO_SOFT_IRQ = 4 << 8
379
+ IRQ_INFO_PRIV_SOFT_EXC = 5 << 8
380
+ IRQ_INFO_SOFT_EXC = 6 << 8
381
+
382
+ IRQ_INFO_ERROR_VALID = 1 << 11
383
+ IRQ_INFO_VALID = 1 << 31
384
+ end
@@ -0,0 +1,62 @@
1
+ require "ffi"
2
+
3
+ module Hypervisor
4
+ module Framework
5
+ extend FFI::Library
6
+
7
+ ffi_lib "/System/Library/Frameworks/Hypervisor.framework/Hypervisor"
8
+
9
+ attach_function :valloc, [:size_t], :pointer
10
+ attach_function :free, [:pointer], :void
11
+
12
+ attach_function :hv_vm_create, [:uint64_t], :uint
13
+ attach_function :hv_vm_destroy, [], :uint
14
+ attach_function :hv_vm_map, [:pointer, :uint64_t, :size_t, :uint64_t], :uint
15
+ attach_function :hv_vm_unmap, [:uint64_t, :size_t], :uint
16
+ attach_function :hv_vm_protect, [:uint64_t, :size_t, :uint64_t], :uint
17
+ attach_function :hv_vm_sync_tsc, [:uint64_t], :uint
18
+
19
+ attach_function :hv_vcpu_create, [:pointer, :uint64_t], :uint
20
+ attach_function :hv_vcpu_destroy, [:uint], :uint
21
+ attach_function :hv_vcpu_read_register, [:uint, :int, :pointer], :uint
22
+ attach_function :hv_vcpu_write_register, [:uint, :int, :uint64_t], :uint
23
+ attach_function :hv_vcpu_read_fpstate, [:uint, :pointer, :size_t], :uint
24
+ attach_function :hv_vcpu_write_fpstate, [:uint, :pointer, :size_t], :uint
25
+ attach_function :hv_vcpu_enable_native_msr, [:uint, :uint32_t, :bool], :uint
26
+ attach_function :hv_vcpu_read_msr, [:uint, :uint32_t, :pointer], :uint
27
+ attach_function :hv_vcpu_write_msr, [:uint, :uint32_t, :uint64_t], :uint
28
+ attach_function :hv_vcpu_flush, [:uint], :uint
29
+ attach_function :hv_vcpu_invalidate_tlb, [:uint], :uint
30
+ attach_function :hv_vcpu_run, [:uint], :uint, blocking: true
31
+ attach_function :hv_vcpu_interrupt, [:pointer, :uint], :uint
32
+ attach_function :hv_vcpu_get_exec_time, [:uint, :pointer], :uint
33
+
34
+ attach_function :hv_vmx_vcpu_read_vmcs, [:uint, :uint32_t, :pointer], :uint
35
+ attach_function :hv_vmx_vcpu_write_vmcs, [:uint, :uint32_t, :uint64_t], :uint
36
+ attach_function :hv_vmx_read_capability, [:int, :pointer], :uint
37
+ attach_function :hv_vmx_vcpu_set_apic_address, [:int, :uint64_t], :uint
38
+
39
+ def self.return_t(result)
40
+ unless result == 0
41
+ case result
42
+ when SUCCESS
43
+ return
44
+ when ERROR
45
+ raise "Error"
46
+ when BUSY
47
+ raise "Busy"
48
+ when BAD_ARGUMENT
49
+ raise "Bad Argument"
50
+ when NO_RESOURCES
51
+ raise "No Resources"
52
+ when NO_DEVICE
53
+ raise "No Device"
54
+ when UNSUPPORTED
55
+ raise "Hypervisor.framework is not supported on your computer"
56
+ else
57
+ raise "Something went wrong #{result}"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,139 @@
1
+ module Hypervisor
2
+ class VCPU
3
+ def initialize(flags = VCPU_DEFAULT)
4
+ FFI::MemoryPointer.new(:uint, 1) do |vcpu|
5
+ Framework.return_t(Framework.hv_vcpu_create(vcpu, flags))
6
+
7
+ @vcpu = vcpu.get_uint(0)
8
+ end
9
+ end
10
+
11
+ def destroy!
12
+ Framework.return_t(Framework.hv_vcpu_destroy(@vcpu))
13
+ end
14
+
15
+ def flush
16
+ Framework.return_t(Framework.hv_vcpu_flush(@vcpu))
17
+ end
18
+
19
+ def invalidate_tlb
20
+ Framework.return_t(Framework.hv_vcpu_invalidate_tlb(@vcpu))
21
+ end
22
+
23
+ def run
24
+ Framework.return_t(Framework.hv_vcpu_run(@vcpu))
25
+ end
26
+
27
+ def read_register(register)
28
+ FFI::MemoryPointer.new(:uint64_t, 1) do |value|
29
+ Framework.return_t(Framework.hv_vcpu_read_register(@vcpu, register, value))
30
+
31
+ return value.get_uint64(0)
32
+ end
33
+ end
34
+
35
+ def write_register(register, value)
36
+ Framework.return_t(Framework.hv_vcpu_write_register(@vcpu, register, value))
37
+ end
38
+
39
+ def read_vmcs(field)
40
+ FFI::MemoryPointer.new(:uint64_t, 1) do |value|
41
+ Framework.return_t(Framework.hv_vmx_vcpu_read_vmcs(@vcpu, field, value))
42
+
43
+ return value.get_uint64(0)
44
+ end
45
+ end
46
+
47
+ def write_vmcs(field, value)
48
+ Framework.return_t(Framework.hv_vmx_vcpu_write_vmcs(@vcpu, field, value))
49
+ end
50
+
51
+ # Helpers
52
+
53
+ [:a, :b, :c, :d].each do |register|
54
+ const = Hypervisor.const_get("X86_R#{register.upcase}X")
55
+
56
+ define_method("r#{register}x") do
57
+ read_register(const)
58
+ end
59
+
60
+ define_method("r#{register}x=") do |value|
61
+ write_register(const, value)
62
+ end
63
+
64
+ define_method("e#{register}x") do
65
+ read_register(const) & 0xffffffff
66
+ end
67
+
68
+ define_method("e#{register}x=") do |value|
69
+ write_register(const, value & 0xffffffff)
70
+ end
71
+
72
+ define_method("#{register}x") do
73
+ read_register(const) & 0xffff
74
+ end
75
+
76
+ define_method("#{register}x=") do |value|
77
+ write_register(const, value & 0xffff)
78
+ end
79
+
80
+ define_method("#{register}l") do
81
+ read_register(const) & 0xff
82
+ end
83
+
84
+ define_method("#{register}l=") do |value|
85
+ old = read_register(const) & 0xff00
86
+
87
+ write_register(const, old | (value & 0xff))
88
+ end
89
+
90
+ define_method("#{register}h") do
91
+ (read_register(const) & 0xff00) >> 8
92
+ end
93
+
94
+ define_method("#{register}h=") do |value|
95
+ old = read_register(const) & 0xff
96
+
97
+ write_register(const, old | ((value & 0xff) << 8))
98
+ end
99
+ end
100
+
101
+ [:cs, :ss, :ds, :es, :fs, :gs].each do |register|
102
+ const = Hypervisor.const_get("X86_#{register.upcase}")
103
+
104
+ define_method(register) do
105
+ read_register(const)
106
+ end
107
+
108
+ define_method("#{register}=") do |value|
109
+ write_register(const, value)
110
+ end
111
+ end
112
+
113
+ def flags
114
+ read_register(Hypervisor::X86_RFLAGS)
115
+ end
116
+
117
+ def flags=(value)
118
+ write_register(Hypervisor::X86_RFLAGS, value)
119
+ end
120
+
121
+ { cf: 0, pf: 2, af: 4, zf: 6, sf: 7, tf: 8, if: 9, df: 10, of: 11, rf: 16, vm: 17, ac: 18, vif: 19, vip: 20, id: 21 }.each do |register, offset|
122
+ define_method(register) do
123
+ flags[offset]
124
+ end
125
+
126
+ mask = (1 << offset)
127
+
128
+ define_method("#{register}=") do |value|
129
+ old = flags & ~mask
130
+
131
+ if value == 0
132
+ write_register(Hypervisor::X86_RFLAGS, old)
133
+ else
134
+ write_register(Hypervisor::X86_RFLAGS, old | mask)
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,3 @@
1
+ module Hypervisor
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hypervisor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aurora
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-01-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ffi
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.9'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.9'
69
+ description: A wrapper for Hypervisor.framework on macOS
70
+ email:
71
+ - aurora@aventine.se
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - examples/dos
86
+ - hypervisor.gemspec
87
+ - lib/hypervisor.rb
88
+ - lib/hypervisor/constants.rb
89
+ - lib/hypervisor/framework.rb
90
+ - lib/hypervisor/vcpu.rb
91
+ - lib/hypervisor/version.rb
92
+ homepage: https://github.com/rawrasaur/hvpervisor
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.7.7
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Hypervisor for macOS
116
+ test_files: []