<commit_before>//
// Bareflank Extended APIs
// Copyright (C) 2018 Assured Information Security, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

// TIDY_EXCLUSION=-performance-move-const-arg
//
// Reason:
//     Tidy complains that the std::move(d)'s used in the add_handler calls
//     have no effect. Removing std::move however results in a compiler error
//     saying the lvalue (d) can't bind to the rvalue.
//

#include <hve/arch/intel_x64/vcpu.h>

namespace eapis::intel_x64
{

io_instruction_handler::io_instruction_handler(
    gsl::not_null<vcpu *> vcpu
) :
    m_vcpu{vcpu},
    m_io_bitmap_a{vcpu->m_io_bitmap_a.get(), ::x64::pt::page_size},
    m_io_bitmap_b{vcpu->m_io_bitmap_b.get(), ::x64::pt::page_size}
{
    using namespace vmcs_n;

    vcpu->add_handler(
        exit_reason::basic_exit_reason::io_instruction,
        ::handler_delegate_t::create<io_instruction_handler, &io_instruction_handler::handle>(this)
    );
}

// -----------------------------------------------------------------------------
// Add Handler
// -----------------------------------------------------------------------------

void
io_instruction_handler::add_handler(
    vmcs_n::value_type port,
    const handler_delegate_t &in_d,
    const handler_delegate_t &out_d)
{
    m_in_handlers[port].push_front(std::move(in_d));
    m_out_handlers[port].push_front(std::move(out_d));
}

void
io_instruction_handler::emulate(vmcs_n::value_type port)
{ m_emulate[port] = true; }

void
io_instruction_handler::set_default_handler(
    const ::handler_delegate_t &d)
{ m_default_handler = d; }

// -----------------------------------------------------------------------------
// Enablers
// -----------------------------------------------------------------------------

void
io_instruction_handler::trap_on_access(vmcs_n::value_type port)
{
    if (port < 0x8000) {
        set_bit(m_io_bitmap_a, port);
        return;
    }

    if (port < 0x10000) {
        set_bit(m_io_bitmap_b, port);
        return;
    }

    throw std::runtime_error("invalid port: " + std::to_string(port));
}

void
io_instruction_handler::trap_on_all_accesses()
{
    gsl::memset(m_io_bitmap_a, 0xFF);
    gsl::memset(m_io_bitmap_b, 0xFF);
}

void
io_instruction_handler::pass_through_access(vmcs_n::value_type port)
{
    if (port < 0x8000) {
        clear_bit(m_io_bitmap_a, port);
        return;
    }

    if (port < 0x10000) {
        clear_bit(m_io_bitmap_b, port);
        return;
    }

    throw std::runtime_error("invalid port: " + std::to_string(port));
}

void
io_instruction_handler::pass_through_all_accesses()
{
    gsl::memset(m_io_bitmap_a, 0x0);
    gsl::memset(m_io_bitmap_b, 0x0);
}

// -----------------------------------------------------------------------------
// Handlers
// -----------------------------------------------------------------------------

bool<commit_msg>IO bug<commit_after>//
// Bareflank Extended APIs
// Copyright (C) 2018 Assured Information Security, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

// TIDY_EXCLUSION=-performance-move-const-arg
//
// Reason:
//     Tidy complains that the std::move(d)'s used in the add_handler calls
//     have no effect. Removing std::move however results in a compiler error
//     saying the lvalue (d) can't bind to the rvalue.
//

#include <hve/arch/intel_x64/vcpu.h>

namespace eapis::intel_x64
{

io_instruction_handler::io_instruction_handler(
    gsl::not_null<vcpu *> vcpu
) :
    m_vcpu{vcpu},
    m_io_bitmap_a{vcpu->m_io_bitmap_a.get(), ::x64::pt::page_size},
    m_io_bitmap_b{vcpu->m_io_bitmap_b.get(), ::x64::pt::page_size}
{
    using namespace vmcs_n;

    vcpu->add_handler(
        exit_reason::basic_exit_reason::io_instruction,
        ::handler_delegate_t::create<io_instruction_handler, &io_instruction_handler::handle>(this)
    );
}

// -----------------------------------------------------------------------------
// Add Handler
// -----------------------------------------------------------------------------

void
io_instruction_handler::add_handler(
    vmcs_n::value_type port,
    const handler_delegate_t &in_d,
    const handler_delegate_t &out_d)
{
    m_in_handlers[port].push_front(std::move(in_d));
    m_out_handlers[port].push_front(std::move(out_d));
}

void
io_instruction_handler::emulate(vmcs_n::value_type port)
{ m_emulate[port] = true; }

void
io_instruction_handler::set_default_handler(
    const ::handler_delegate_t &d)
{ m_default_handler = d; }

// -----------------------------------------------------------------------------
// Enablers
// -----------------------------------------------------------------------------

void
io_instruction_handler::trap_on_access(vmcs_n::value_type port)
{
    if (port < 0x8000) {
        set_bit(m_io_bitmap_a, port);
        return;
    }

    if (port < 0x10000) {
        set_bit(m_io_bitmap_b, port - 0x8000);
        return;
    }

    throw std::runtime_error("invalid port: " + std::to_string(port));
}

void
io_instruction_handler::trap_on_all_accesses()
{
    gsl::memset(m_io_bitmap_a, 0xFF);
    gsl::memset(m_io_bitmap_b, 0xFF);
}

void
io_instruction_handler::pass_through_access(vmcs_n::value_type port)
{
    if (port < 0x8000) {
        clear_bit(m_io_bitmap_a, port);
        return;
    }

    if (port < 0x10000) {
        clear_bit(m_io_bitmap_b, port - 0x8000);
        return;
    }

    throw std::runtime_error("invalid port: " + std::to_string(port));
}

void
io_instruction_handler::pass_through_all_accesses()
{
    gsl::memset(m_io_bitmap_a, 0x0);
    gsl::memset(m_io_bitmap_b, 0x0);
}

// -----------------------------------------------------------------------------
// Handlers
// -----------------------------------------------------------------------------

bool
{'fraction_non_alphanumeric': 0.23138409760201936, 'fraction_numerical': 0.016267003225354088, 'mean_word_length': 2.2126126126126127, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5896379', 'n_tokens_mistral': 2284, 'n_tokens_neox': 2177, 'n_words': 516}