hypervisor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []