mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 21:32:57 +00:00
parent
3a566262fe
commit
5abd2dddb8
@ -28,6 +28,7 @@ namespace Genode {
|
||||
*/
|
||||
struct Vm_state;
|
||||
using Vm_data = Vm_state;
|
||||
struct Vcpu_state;
|
||||
}
|
||||
|
||||
|
||||
@ -46,4 +47,6 @@ struct Genode::Vm_state : Genode::Cpu_state_modes
|
||||
Genode::addr_t irq_injection;
|
||||
};
|
||||
|
||||
struct Genode::Vcpu_state : Genode::Vm_state { };
|
||||
|
||||
#endif /* _INCLUDE__SPEC__IMX53__VM_STATE_H_ */
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* \brief Paravirtualized access to block devices for VMs
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2015-10-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -99,58 +100,58 @@ Block_driver::Block_driver(Env &env,
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_name(Vm_base &vm)
|
||||
void Block_driver::_name(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() },
|
||||
_dev_apply(Device::Id { state.r2 },
|
||||
[&] (Device &dev) { copy_cstring((char *)_buf, dev.name().string(), _buf_size); },
|
||||
[&] () { ((char *)_buf)[0] = 0; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_block_count(Vm_base &vm)
|
||||
void Block_driver::_block_count(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() },
|
||||
[&] (Device &dev) { vm.smc_ret(dev.block_count()); },
|
||||
[&] () { vm.smc_ret(0); });
|
||||
_dev_apply(Device::Id { state.r2 },
|
||||
[&] (Device &dev) { state.r0 = dev.block_count(); },
|
||||
[&] () { state.r0 = 0; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_block_size(Vm_base &vm)
|
||||
void Block_driver::_block_size(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() },
|
||||
[&] (Device &dev) { vm.smc_ret(dev.block_size()); },
|
||||
[&] () { vm.smc_ret(0); });
|
||||
_dev_apply(Device::Id { state.r2 },
|
||||
[&] (Device &dev) { state.r0 = dev.block_size(); },
|
||||
[&] () { state.r0 = 0; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_queue_size(Vm_base &vm)
|
||||
void Block_driver::_queue_size(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() },
|
||||
[&] (Device &dev) { vm.smc_ret(dev.session().tx()->bulk_buffer_size()); },
|
||||
[&] () { vm.smc_ret(0); });
|
||||
_dev_apply(Device::Id { state.r2 },
|
||||
[&] (Device &dev) { state.r0 = dev.session().tx()->bulk_buffer_size(); },
|
||||
[&] () { state.r0 = 0; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_writeable(Vm_base &vm)
|
||||
void Block_driver::_writeable(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() },
|
||||
[&] (Device &dev) { vm.smc_ret(dev.writeable()); },
|
||||
[&] () { vm.smc_ret(false); });
|
||||
_dev_apply(Device::Id { state.r2 },
|
||||
[&] (Device &dev) { state.r0 = dev.writeable(); },
|
||||
[&] () { state.r0 = false; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_irq(Vm_base &vm)
|
||||
void Block_driver::_irq(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() },
|
||||
[&] (Device &dev) { vm.smc_ret(dev.irq()); },
|
||||
[&] () { vm.smc_ret(~(unsigned)0); });
|
||||
_dev_apply(Device::Id { state.r2 },
|
||||
[&] (Device &dev) { state.r0 = dev.irq(); },
|
||||
[&] () { state.r0 = ~(unsigned)0; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_buffer(Vm_base &vm)
|
||||
void Block_driver::_buffer(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
addr_t const buf_base = vm.smc_arg_2();
|
||||
_buf_size = vm.smc_arg_3();
|
||||
addr_t const buf_base = state.r2;
|
||||
_buf_size = state.r3;
|
||||
addr_t const buf_top = buf_base + _buf_size;
|
||||
Ram const &ram = vm.ram();
|
||||
addr_t const ram_top = ram.base() + ram.size();
|
||||
@ -168,17 +169,18 @@ void Block_driver::_buffer(Vm_base &vm)
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_new_request(Vm_base &vm)
|
||||
void Block_driver::_new_request(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
auto dev_func = [&] (Device &dev) {
|
||||
try {
|
||||
size_t const size = vm.smc_arg_3();
|
||||
void *const req = (void*)vm.smc_arg_4();
|
||||
size_t const size = state.r3;
|
||||
void *const req = (void*)state.r4;
|
||||
|
||||
Packet_descriptor pkt = dev.session().alloc_packet(size);
|
||||
void *addr = dev.session().tx()->packet_content(pkt);
|
||||
dev.cache().insert(addr, req);
|
||||
vm.smc_ret((long)addr, pkt.offset());
|
||||
state.r0 = (long)addr;
|
||||
state.r1 = pkt.offset();
|
||||
}
|
||||
catch (Request_cache::Full) {
|
||||
error("block request cache full");
|
||||
@ -189,20 +191,23 @@ void Block_driver::_new_request(Vm_base &vm)
|
||||
throw Device_function_failed();
|
||||
}
|
||||
};
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() }, dev_func, [&] () { vm.smc_ret(0, 0); });
|
||||
_dev_apply(Device::Id { state.r2 }, dev_func, [&] () {
|
||||
state.r0 = 0;
|
||||
state.r1 = 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_submit_request(Vm_base &vm)
|
||||
void Block_driver::_submit_request(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
auto dev_func = [&] (Device &dev) {
|
||||
|
||||
off_t const queue_offset = vm.smc_arg_3();
|
||||
size_t const size = vm.smc_arg_4();
|
||||
bool const write = vm.smc_arg_7();
|
||||
void *const dst = (void *)vm.smc_arg_8();
|
||||
off_t const queue_offset = state.r3;
|
||||
size_t const size = state.r4;
|
||||
bool const write = state.r7;
|
||||
void *const dst = (void *)state.r8;
|
||||
unsigned long long const disc_offset =
|
||||
(unsigned long long)vm.smc_arg_5() << 32 | vm.smc_arg_6();
|
||||
(unsigned long long)state.r5 << 32 | state.r6;
|
||||
|
||||
if (write) {
|
||||
if (size > _buf_size) {
|
||||
@ -220,11 +225,11 @@ void Block_driver::_submit_request(Vm_base &vm)
|
||||
|
||||
dev.session().tx()->submit_packet(pkt);
|
||||
};
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() }, dev_func, [] () { });
|
||||
_dev_apply(Device::Id { state.r2 }, dev_func, [] () { });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::_collect_reply(Vm_base &vm)
|
||||
void Block_driver::_collect_reply(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
auto dev_func = [&] (Device &dev) {
|
||||
|
||||
@ -250,7 +255,7 @@ void Block_driver::_collect_reply(Vm_base &vm)
|
||||
|
||||
/* check for packets and tell VM to stop if none available */
|
||||
if (!dev.session().tx()->ack_avail()) {
|
||||
vm.smc_ret(0);
|
||||
state.r0 = 0;
|
||||
return;
|
||||
}
|
||||
/* lookup request of next packet and free cache slot */
|
||||
@ -269,13 +274,13 @@ void Block_driver::_collect_reply(Vm_base &vm)
|
||||
}
|
||||
construct_at<Reply>(_buf, req, write, dat_size, dat);
|
||||
dev.session().tx()->release_packet(pkt);
|
||||
vm.smc_ret(1);
|
||||
state.r0 = 1;
|
||||
};
|
||||
_dev_apply(Device::Id { vm.smc_arg_2() }, dev_func, [&] () { vm.smc_ret(-1); });
|
||||
_dev_apply(Device::Id { state.r2 }, dev_func, [&] () { state.r0 = -1; });
|
||||
}
|
||||
|
||||
|
||||
void Block_driver::handle_smc(Vm_base &vm)
|
||||
void Block_driver::handle_smc(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
enum {
|
||||
DEVICE_COUNT = 0,
|
||||
@ -291,22 +296,22 @@ void Block_driver::handle_smc(Vm_base &vm)
|
||||
BUFFER = 10,
|
||||
NAME = 11,
|
||||
};
|
||||
switch (vm.smc_arg_1()) {
|
||||
case DEVICE_COUNT: vm.smc_ret(_dev_count); break;
|
||||
case BLOCK_COUNT: _block_count(vm); break;
|
||||
case BLOCK_SIZE: _block_size(vm); break;
|
||||
case WRITEABLE: _writeable(vm); break;
|
||||
case QUEUE_SIZE: _queue_size(vm); break;
|
||||
case IRQ: _irq(vm); break;
|
||||
switch (state.r1) {
|
||||
case DEVICE_COUNT: state.r0 = _dev_count; break;
|
||||
case BLOCK_COUNT: _block_count(vm, state); break;
|
||||
case BLOCK_SIZE: _block_size(vm, state); break;
|
||||
case WRITEABLE: _writeable(vm, state); break;
|
||||
case QUEUE_SIZE: _queue_size(vm, state); break;
|
||||
case IRQ: _irq(vm, state); break;
|
||||
case START_CALLBACK: _devs.for_each<Device>([&] (Device &dev)
|
||||
{ dev.start_irq_handling(); }); break;
|
||||
case NEW_REQUEST: _new_request(vm); break;
|
||||
case SUBMIT_REQUEST: _submit_request(vm); break;
|
||||
case COLLECT_REPLY: _collect_reply(vm); break;
|
||||
case BUFFER: _buffer(vm); break;
|
||||
case NAME: _name(vm); break;
|
||||
case NEW_REQUEST: _new_request(vm, state); break;
|
||||
case SUBMIT_REQUEST: _submit_request(vm, state); break;
|
||||
case COLLECT_REPLY: _collect_reply(vm, state); break;
|
||||
case BUFFER: _buffer(vm, state); break;
|
||||
case NAME: _name(vm, state); break;
|
||||
default:
|
||||
error("unknown block-driver function ", vm.smc_arg_1());
|
||||
error("unknown block-driver function ", state.r1);
|
||||
throw Vm_base::Exception_handling_failed();
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* \brief Paravirtualized access to block devices for VMs
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2015-10-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -119,17 +120,17 @@ class Genode::Block_driver
|
||||
Allocator_avl _dev_alloc;
|
||||
|
||||
void _buf_to_pkt(void *dst, size_t sz);
|
||||
void _name(Vm_base &vm);
|
||||
void _block_count(Vm_base &vm);
|
||||
void _block_size(Vm_base &vm);
|
||||
void _queue_size(Vm_base &vm);
|
||||
void _writeable(Vm_base &vm);
|
||||
void _irq(Vm_base &vm);
|
||||
void _buffer(Vm_base &vm);
|
||||
void _device_count(Vm_base &vm);
|
||||
void _new_request(Vm_base &vm);
|
||||
void _submit_request(Vm_base &vm);
|
||||
void _collect_reply(Vm_base &vm);
|
||||
void _name(Vm_base &vm, Vcpu_state &state);
|
||||
void _block_count(Vm_base &vm, Vcpu_state &state);
|
||||
void _block_size(Vm_base &vm, Vcpu_state &state);
|
||||
void _queue_size(Vm_base &vm, Vcpu_state &state);
|
||||
void _writeable(Vm_base &vm, Vcpu_state &state);
|
||||
void _irq(Vm_base &vm, Vcpu_state &state);
|
||||
void _buffer(Vm_base &vm, Vcpu_state &state);
|
||||
void _device_count(Vm_base &vm, Vcpu_state &state);
|
||||
void _new_request(Vm_base &vm, Vcpu_state &state);
|
||||
void _submit_request(Vm_base &vm, Vcpu_state &state);
|
||||
void _collect_reply(Vm_base &vm, Vcpu_state &state);
|
||||
|
||||
template <typename DEV_FUNC, typename ERR_FUNC>
|
||||
void _dev_apply(Device::Id id,
|
||||
@ -146,7 +147,7 @@ class Genode::Block_driver
|
||||
|
||||
public:
|
||||
|
||||
void handle_smc(Vm_base &vm);
|
||||
void handle_smc(Vm_base &vm, Vcpu_state &state);
|
||||
|
||||
Block_driver(Env &env,
|
||||
Xml_node config,
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* \brief Paravirtualized access to serial device for a Trustzone VM
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2015-10-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -34,11 +35,11 @@ class Genode::Serial_driver
|
||||
|
||||
void _push(char c) { _buf.local_addr<char>()[_off++] = c; }
|
||||
void _flush();
|
||||
void _send(Vm_base &vm);
|
||||
void _send(Vm_base &vm, Vcpu_state &state);
|
||||
|
||||
public:
|
||||
|
||||
void handle_smc(Vm_base &vm);
|
||||
void handle_smc(Vm_base &vm, Vcpu_state &state);
|
||||
|
||||
Serial_driver(Ram_allocator &ram, Region_map &local_rm)
|
||||
: _buf(ram, local_rm, BUF_SIZE) { }
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Virtual Machine Monitor VM definition
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2012-06-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -74,9 +75,8 @@ class Genode::Vm_base : Noncopyable, Interface
|
||||
Vm_connection _vm { _env };
|
||||
Vm_connection::Exit_config _exit_config { };
|
||||
Vm_connection::Vcpu _vcpu;
|
||||
Vm_state &_state { *(Vm_state *)&_vcpu.state() };
|
||||
|
||||
void _load_kernel();
|
||||
void _load_kernel(Vcpu_state &);
|
||||
|
||||
virtual void _load_kernel_surroundings() = 0;
|
||||
virtual addr_t _board_info_offset() const = 0;
|
||||
@ -97,30 +97,18 @@ class Genode::Vm_base : Noncopyable, Interface
|
||||
Allocator &alloc,
|
||||
Vcpu_handler_base &handler);
|
||||
|
||||
void run() { _vcpu.run(); }
|
||||
void pause() { _vcpu.pause(); }
|
||||
|
||||
void start();
|
||||
void dump();
|
||||
void start(Vcpu_state &);
|
||||
void dump(Vcpu_state &);
|
||||
void inject_irq(unsigned irq);
|
||||
addr_t va_to_pa(addr_t va);
|
||||
addr_t va_to_pa(Vcpu_state &state, addr_t va);
|
||||
|
||||
Vm_state const &state() const { return _state; }
|
||||
Ram const &ram() const { return _ram; }
|
||||
|
||||
addr_t smc_arg_0() { return _state.r0; }
|
||||
addr_t smc_arg_1() { return _state.r1; }
|
||||
addr_t smc_arg_2() { return _state.r2; }
|
||||
addr_t smc_arg_3() { return _state.r3; }
|
||||
addr_t smc_arg_4() { return _state.r4; }
|
||||
addr_t smc_arg_5() { return _state.r5; }
|
||||
addr_t smc_arg_6() { return _state.r6; }
|
||||
addr_t smc_arg_7() { return _state.r7; }
|
||||
addr_t smc_arg_8() { return _state.r8; }
|
||||
addr_t smc_arg_9() { return _state.r9; }
|
||||
|
||||
void smc_ret(addr_t const ret_0) { _state.r0 = ret_0; }
|
||||
void smc_ret(addr_t const ret_0, addr_t const ret_1);
|
||||
template<typename FN>
|
||||
void with_state(FN const & fn)
|
||||
{
|
||||
_vcpu.with_state(fn);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _VM_BASE_H_ */
|
||||
|
@ -1,11 +1,12 @@
|
||||
/*
|
||||
* \brief Paravirtualized access to serial device for a Trustzone VM
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2015-10-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2015-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -25,9 +26,9 @@ void Serial_driver::_flush()
|
||||
}
|
||||
|
||||
|
||||
void Serial_driver::_send(Vm_base &vm)
|
||||
void Serial_driver::_send(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
char const c = vm.smc_arg_2();
|
||||
char const c = state.r2;
|
||||
if (c == '\n') {
|
||||
_flush();
|
||||
} else {
|
||||
@ -38,10 +39,10 @@ void Serial_driver::_send(Vm_base &vm)
|
||||
}
|
||||
|
||||
|
||||
void Serial_driver::handle_smc(Vm_base &vm)
|
||||
void Serial_driver::handle_smc(Vm_base &vm, Vcpu_state &state)
|
||||
{
|
||||
enum { SEND = 0 };
|
||||
switch (vm.smc_arg_1()) {
|
||||
case SEND: _send(vm); break;
|
||||
default: error("unknown serial-driver function ", vm.smc_arg_1()); }
|
||||
switch (state.r1) {
|
||||
case SEND: _send(vm, state); break;
|
||||
default: error("unknown serial-driver function ", state.r1); }
|
||||
}
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Virtual Machine Monitor
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2012-06-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2008-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2008-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -58,7 +59,7 @@ class Main
|
||||
Serial_driver _serial { _env.ram(), _env.rm() };
|
||||
Block_driver _block { _env, _config.xml(), _heap, _vm };
|
||||
|
||||
void _handle_smc()
|
||||
void _handle_smc(Vcpu_state &state)
|
||||
{
|
||||
enum {
|
||||
FRAMEBUFFER = 0,
|
||||
@ -66,13 +67,13 @@ class Main
|
||||
SERIAL = 2,
|
||||
BLOCK = 3,
|
||||
};
|
||||
switch (_vm.smc_arg_0()) {
|
||||
switch (state.r0) {
|
||||
case FRAMEBUFFER: break;
|
||||
case INPUT: break;
|
||||
case SERIAL: _serial.handle_smc(_vm); break;
|
||||
case BLOCK: _block.handle_smc(_vm); break;
|
||||
case SERIAL: _serial.handle_smc(_vm, state); break;
|
||||
case BLOCK: _block.handle_smc(_vm, state); break;
|
||||
default:
|
||||
error("unknown hypervisor call ", _vm.smc_arg_0());
|
||||
error("unknown hypervisor call ", state.r0);
|
||||
throw Vm::Exception_handling_failed();
|
||||
};
|
||||
}
|
||||
@ -85,19 +86,22 @@ class Main
|
||||
|
||||
void _handle_exception()
|
||||
{
|
||||
_vm.on_vmm_entry();
|
||||
try {
|
||||
switch (_vm.state().cpu_exception) {
|
||||
case Cpu_state::DATA_ABORT: _handle_data_abort(); break;
|
||||
case Cpu_state::SUPERVISOR_CALL: _handle_smc(); break;
|
||||
default:
|
||||
error("unknown exception ", _vm.state().cpu_exception);
|
||||
throw Vm::Exception_handling_failed();
|
||||
_vm.with_state([this](Vcpu_state &state) {
|
||||
_vm.on_vmm_entry();
|
||||
try {
|
||||
switch (state.cpu_exception) {
|
||||
case Cpu_state::DATA_ABORT: _handle_data_abort(); break;
|
||||
case Cpu_state::SUPERVISOR_CALL: _handle_smc(state); break;
|
||||
case VCPU_EXCEPTION_STARTUP: _vm.start(state); break;
|
||||
default:
|
||||
error("unknown exception ", state.cpu_exception);
|
||||
throw Vm::Exception_handling_failed();
|
||||
}
|
||||
}
|
||||
_vm.run();
|
||||
}
|
||||
catch (Vm::Exception_handling_failed) { _vm.dump(); }
|
||||
_vm.on_vmm_exit();
|
||||
catch (Vm::Exception_handling_failed) { _vm.dump(state); }
|
||||
_vm.on_vmm_exit();
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
public:
|
||||
@ -107,8 +111,6 @@ class Main
|
||||
log("Start virtual machine ...");
|
||||
_m4if.set_region0(Trustzone::SECURE_RAM_BASE,
|
||||
Trustzone::SECURE_RAM_SIZE);
|
||||
_vm.start();
|
||||
_vm.run();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Virtual Machine Monitor VM definition
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \author Benjamin Lamowski
|
||||
* \date 2012-06-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012-2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -22,12 +23,12 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Vm_base::_load_kernel()
|
||||
void Vm_base::_load_kernel(Vcpu_state &state)
|
||||
{
|
||||
Attached_rom_dataspace kernel(_env, _kernel.string());
|
||||
memcpy((void*)(_ram.local() + _kernel_off),
|
||||
kernel.local_addr<void>(), kernel.size());
|
||||
_state.ip = _ram.base() + _kernel_off;
|
||||
state.ip = _ram.base() + _kernel_off;
|
||||
}
|
||||
|
||||
|
||||
@ -45,31 +46,33 @@ Vm_base::Vm_base(Env &env,
|
||||
_env(env), _kernel(kernel), _cmdline(cmdline), _kernel_off(kernel_off),
|
||||
_machine(machine), _board(board), _ram(env, ram_base, ram_size),
|
||||
_vcpu(_vm, alloc, handler, _exit_config)
|
||||
{
|
||||
_state.irq_injection = 0;
|
||||
}
|
||||
{ }
|
||||
|
||||
void Vm_base::start()
|
||||
void Vm_base::start(Vcpu_state &state)
|
||||
{
|
||||
memset((void*)&_state, 0, sizeof(Vm_state));
|
||||
_load_kernel();
|
||||
memset((void*)&state, 0, sizeof(Vm_state));
|
||||
_load_kernel(state);
|
||||
_load_kernel_surroundings();
|
||||
_state.cpsr = 0x93; /* SVC mode and IRQs disabled */
|
||||
_state.r0 = 0;
|
||||
_state.r1 = _machine.value;
|
||||
_state.r2 = _ram.base() + _board_info_offset();
|
||||
state.cpsr = 0x93; /* SVC mode and IRQs disabled */
|
||||
state.r0 = 0;
|
||||
state.r1 = _machine.value;
|
||||
state.r2 = _ram.base() + _board_info_offset();
|
||||
state.irq_injection = 0;
|
||||
}
|
||||
|
||||
|
||||
void Vm_base::inject_irq(unsigned irq)
|
||||
{
|
||||
if (_state.irq_injection) { throw Inject_irq_failed(); }
|
||||
_state.irq_injection = irq;
|
||||
with_state([this,irq](Vcpu_state &state) {
|
||||
if (state.irq_injection) { throw Inject_irq_failed(); }
|
||||
state.irq_injection = irq;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Vm_base::dump()
|
||||
void Vm_base::dump(Vcpu_state &state)
|
||||
{
|
||||
char const *mod[] = { "und", "svc", "abt", "irq", "fiq" };
|
||||
char const *exc[] = { "invalid", "reset", "undefined", "smc",
|
||||
@ -77,56 +80,49 @@ void Vm_base::dump()
|
||||
|
||||
auto log_adr_reg = [&] (char const *reg, addr_t val) {
|
||||
log(" ", reg, " = ", Hex(val, Hex::PREFIX, Hex::PAD), " ",
|
||||
Hex(va_to_pa(val), Hex::PREFIX, Hex::PAD)); };
|
||||
Hex(va_to_pa(state, val), Hex::PREFIX, Hex::PAD)); };
|
||||
|
||||
auto log_mod_reg = [&] (char const *reg, addr_t val, char const *mod) {
|
||||
log(" ", reg, "_", mod, " = ", Hex(val, Hex::PREFIX, Hex::PAD), " ",
|
||||
Hex(va_to_pa(val), Hex::PREFIX, Hex::PAD)); };
|
||||
Hex(va_to_pa(state, val), Hex::PREFIX, Hex::PAD)); };
|
||||
|
||||
log("Cpu state:");
|
||||
log(" Register Virt Phys");
|
||||
log("------------------------------------");
|
||||
log_adr_reg("r0 ", _state.r0);
|
||||
log_adr_reg("r1 ", _state.r1);
|
||||
log_adr_reg("r2 ", _state.r2);
|
||||
log_adr_reg("r3 ", _state.r3);
|
||||
log_adr_reg("r4 ", _state.r4);
|
||||
log_adr_reg("r5 ", _state.r5);
|
||||
log_adr_reg("r6 ", _state.r6);
|
||||
log_adr_reg("r7 ", _state.r7);
|
||||
log_adr_reg("r8 ", _state.r8);
|
||||
log_adr_reg("r9 ", _state.r9);
|
||||
log_adr_reg("r10 ", _state.r10);
|
||||
log_adr_reg("r11 ", _state.r11);
|
||||
log_adr_reg("r12 ", _state.r12);
|
||||
log_adr_reg("sp ", _state.sp);
|
||||
log_adr_reg("lr ", _state.lr);
|
||||
log_adr_reg("ip ", _state.ip);
|
||||
log_adr_reg("cpsr ", _state.cpsr);
|
||||
log_adr_reg("r0 ", state.r0);
|
||||
log_adr_reg("r1 ", state.r1);
|
||||
log_adr_reg("r2 ", state.r2);
|
||||
log_adr_reg("r3 ", state.r3);
|
||||
log_adr_reg("r4 ", state.r4);
|
||||
log_adr_reg("r5 ", state.r5);
|
||||
log_adr_reg("r6 ", state.r6);
|
||||
log_adr_reg("r7 ", state.r7);
|
||||
log_adr_reg("r8 ", state.r8);
|
||||
log_adr_reg("r9 ", state.r9);
|
||||
log_adr_reg("r10 ", state.r10);
|
||||
log_adr_reg("r11 ", state.r11);
|
||||
log_adr_reg("r12 ", state.r12);
|
||||
log_adr_reg("sp ", state.sp);
|
||||
log_adr_reg("lr ", state.lr);
|
||||
log_adr_reg("ip ", state.ip);
|
||||
log_adr_reg("cpsr ", state.cpsr);
|
||||
for (unsigned i = 0; i < Vm_state::Mode_state::MAX; i++) {
|
||||
log_mod_reg("sp ", _state.mode[i].sp, mod[i]);
|
||||
log_mod_reg("lr ", _state.mode[i].lr, mod[i]);
|
||||
log_mod_reg("spsr ", _state.mode[i].spsr, mod[i]);
|
||||
log_mod_reg("sp ", state.mode[i].sp, mod[i]);
|
||||
log_mod_reg("lr ", state.mode[i].lr, mod[i]);
|
||||
log_mod_reg("spsr ", state.mode[i].spsr, mod[i]);
|
||||
}
|
||||
log(" ttbr0 = ", Hex(_state.ttbr[0], Hex::PREFIX, Hex::PAD));
|
||||
log(" ttbr1 = ", Hex(_state.ttbr[1], Hex::PREFIX, Hex::PAD));
|
||||
log(" ttbrc = ", Hex(_state.ttbrc , Hex::PREFIX, Hex::PAD));
|
||||
log_adr_reg("dfar ", _state.dfar);
|
||||
log(" exception = ", exc[_state.cpu_exception]);
|
||||
log(" ttbr0 = ", Hex(state.ttbr[0], Hex::PREFIX, Hex::PAD));
|
||||
log(" ttbr1 = ", Hex(state.ttbr[1], Hex::PREFIX, Hex::PAD));
|
||||
log(" ttbrc = ", Hex(state.ttbrc , Hex::PREFIX, Hex::PAD));
|
||||
log_adr_reg("dfar ", state.dfar);
|
||||
log(" exception = ", exc[state.cpu_exception]);
|
||||
}
|
||||
|
||||
|
||||
void Vm_base::smc_ret(addr_t const ret_0, addr_t const ret_1)
|
||||
{
|
||||
_state.r0 = ret_0;
|
||||
_state.r1 = ret_1;
|
||||
}
|
||||
|
||||
|
||||
addr_t Vm_base::va_to_pa(addr_t va)
|
||||
addr_t Vm_base::va_to_pa(Vcpu_state & state, addr_t va)
|
||||
{
|
||||
try {
|
||||
Mmu mmu(_state, _ram);
|
||||
Mmu mmu(state, _ram);
|
||||
return mmu.phys_addr(va);
|
||||
}
|
||||
catch(Ram::Invalid_addr) { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user