blob: fc64547d9c166cf4ce82835994a06d9d774ff208 [file] [log] [blame]
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
extern "C" {
#include "vmapi/hf/abi.h"
}
#include <gmock/gmock.h>
namespace
{
using ::testing::Eq;
/**
* Simulate an uninitialized hf_vcpu_run_return so it can be detected if any
* uninitialized fields make their way into the encoded form which would
* indicate a data leak.
*/
struct hf_vcpu_run_return dirty_vcpu_run_return()
{
struct hf_vcpu_run_return res;
memset(&res, 0xc5, sizeof(res));
return res;
}
/**
* Simulate an uninitialized hf_mailbox_receive_return so it can be detected if
* any uninitialized fields make their way into the encoded form which would
* indicate a data leak.
*/
struct hf_mailbox_receive_return dirty_mailbox_receive_return()
{
struct hf_mailbox_receive_return res;
memset(&res, 0xc5, sizeof(res));
return res;
}
/**
* Encode a preempted response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_preempted)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_PREEMPTED;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(0));
}
/**
* Decode a preempted response ignoring the irrelevant bits.
*/
TEST(abi, hf_vcpu_run_return_decode_preempted)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0x1a1a1a1a2b2b2b00);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_PREEMPTED));
}
/**
* Encode a yield response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_yield)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_YIELD;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(1));
}
/**
* Decode a yield response ignoring the irrelevant bits.
*/
TEST(abi, hf_vcpu_run_return_decode_yield)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0x1a1a1a1a2b2b2b01);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_YIELD));
}
/**
* Encode wait-for-interrupt response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_wait_for_interrupt)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_WAIT_FOR_INTERRUPT;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(2));
}
/**
* Decode a wait-for-interrupt response ignoring the irrelevant bits.
*/
TEST(abi, hf_vcpu_run_return_decode_wait_for_interrupt)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0x1234abcdbadb0102);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_WAIT_FOR_INTERRUPT));
}
/**
* Encode wake up response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_wake_up)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_WAKE_UP;
res.wake_up.vm_id = 0x12345678;
res.wake_up.vcpu = 0xabcd;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(0x12345678abcd0003));
}
/**
* Decode a wake up response ignoring the irrelevant bits.
*/
TEST(abi, hf_vcpu_run_return_decode_wake_up)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0xbeefd00df00daf03);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_WAKE_UP));
EXPECT_THAT(res.wake_up.vm_id, Eq(0xbeefd00d));
EXPECT_THAT(res.wake_up.vcpu, Eq(0xf00d));
}
/**
* Encode message response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_message)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_MESSAGE;
res.message.size = 0xdeadbeef;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(0xdeadbeef00000004));
}
/**
* Decode a wake up response ignoring the irrelevant bits.
*/
TEST(abi, hf_vcpu_run_return_decode_message)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0x1123581314916204);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_MESSAGE));
EXPECT_THAT(res.message.size, Eq(0x11235813));
}
/**
* Encode sleep response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_sleep)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_SLEEP;
res.sleep.ns = 0xcafed00dfeeded;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(0xcafed00dfeeded05));
}
/**
* Encoding a sleep response with too large a sleep duration will drop the top
* octet.
*/
TEST(abi, hf_vcpu_run_return_encode_sleep_too_long)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_SLEEP;
res.sleep.ns = 0xcc88888888888888;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(0x8888888888888805));
}
/**
* Decode a sleep response.
*/
TEST(abi, hf_vcpu_run_return_decode_sleep)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0x1a2b3c4d5e6f7705);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_SLEEP));
EXPECT_THAT(res.sleep.ns, Eq(0x1a2b3c4d5e6f77));
}
/**
* Encode a mailbox receive response without leaking.
*/
TEST(abi, hf_mailbox_receive_return_encode)
{
struct hf_mailbox_receive_return res = dirty_mailbox_receive_return();
res.vm_id = 0x12345678;
res.size = 0xaabbccdd;
EXPECT_THAT(hf_mailbox_receive_return_encode(res),
Eq(0xaabbccdd12345678));
}
/**
* Decode a mailbox receive response.
*/
TEST(abi, hf_mailbox_receive_return_decode)
{
struct hf_mailbox_receive_return res =
hf_mailbox_receive_return_decode(0X8badf00d00ddba11);
EXPECT_THAT(res.vm_id, Eq(0X00ddba11));
EXPECT_THAT(res.size, Eq(0x8badf00d));
}
/**
* Encode a 'notify waiters' response without leaking.
*/
TEST(abi, hf_vcpu_run_return_encode_interrupt)
{
struct hf_vcpu_run_return res = dirty_vcpu_run_return();
res.code = HF_VCPU_RUN_NOTIFY_WAITERS;
EXPECT_THAT(hf_vcpu_run_return_encode(res), Eq(6));
}
/**
* Decode a 'notify waiters' response ignoring the irrelevant bits.
*/
TEST(abi, hf_vcpu_run_return_decode_interrupt)
{
struct hf_vcpu_run_return res =
hf_vcpu_run_return_decode(0x1a1a1a1a2b2b2b06);
EXPECT_THAT(res.code, Eq(HF_VCPU_RUN_NOTIFY_WAITERS));
}
} /* namespace */