blob: d7091cdf75e5596220ed0f17ef987751eb6798c6 [file] [log] [blame]
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef VM_TOOLS_CONCIERGE_MANATEE_MEMORY_SERVICE_H_
#define VM_TOOLS_CONCIERGE_MANATEE_MEMORY_SERVICE_H_
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include <base/files/scoped_file.h>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/threading/thread.h>
#include "vm_tools/concierge/balloon_policy.h"
#include "vm_tools/concierge/vm_interface.h"
namespace vm_tools {
namespace concierge {
using TaggedBalloonStats = std::vector<std::pair<VmMemoryId, BalloonStats>>;
using TaggedMemoryMiBDeltas = std::vector<std::pair<VmMemoryId, int64_t>>;
// Class responsible for communicating with the ManaTEE memory service, to
// manage the memory allocation between the various VMs.
class ManateeMemoryService {
public:
static std::unique_ptr<ManateeMemoryService> Create(
base::ScopedFD mms_socket);
~ManateeMemoryService() = default;
// Get balloon stats for the specified ids.
void GetBalloonStats(std::vector<VmMemoryId> ids,
base::OnceCallback<void(TaggedBalloonStats)> stats_cb);
// Rebalance memory according to the requested deltas.
//
// For each VM specified by a VmMemoryId, modify its memory allocation
// by the corresponding delta.
//
// |rebalance_cb| is invoked with the argument specifying whether
// the specified deltas were fully applied. Note that the deltas
// may be partially applied even if the result is false.
void RebalanceMemory(TaggedMemoryMiBDeltas deltas,
base::OnceCallback<void(bool)> rebalance_cb);
// Launch a new VM whose memory size is |mem_size_mb|.
//
// |start_vm_cb| will be invoked only if the manatee memory service can
// reserve enough memory for the new VM. The caller should start the new VM
// using the given VmMemoryId.
//
// |result_cb| will be invoked with the argument specifying whether or not
// the VM was successfully launched. This is always invoked. Note that this
// can be invoked even if |start_vm_cb| is invoked and succeeds.
//
// |stop_vm_cb| will be invoked before |result_cb| if an error occurs during
// startup after |start_vm_cb| has been invoked successfully. The callback
// must stop the VM and remove it via RemoveVm.
void LaunchVm(int64_t mem_size_mb,
base::OnceCallback<bool(VmMemoryId id)> start_vm_cb,
base::OnceCallback<void(void)> stop_vm_cb,
base::OnceCallback<void(bool)> result_cb);
// Cleans up manatee memory service state associated with the VM |id|.
void RemoveVm(VmMemoryId id);
private:
explicit ManateeMemoryService(base::ScopedFD mms_socket);
ManateeMemoryService(const ManateeMemoryService&) = delete;
ManateeMemoryService& operator=(const ManateeMemoryService&) = delete;
bool Init();
TaggedBalloonStats GetBalloonStatsOnThread(std::vector<VmMemoryId> ids);
bool RebalanceMemoryOnThread(TaggedMemoryMiBDeltas deltas,
int64_t reserve_delta);
bool LaunchVmOnThread(int64_t mem_size_mb,
base::OnceCallback<bool(VmMemoryId)> start_vm_cb,
base::OnceCallback<void(void)> stop_vm_cb,
scoped_refptr<base::SequencedTaskRunner> cb_runner);
bool RebalanceForNewVmOnThread(int64_t init_mem_size, int64_t mem_size);
void ResetReservedMemoryOnThread(int64_t old_reserves);
void RemoveVmOnThread(VmMemoryId id);
// A worker thread on which to communicate with ManaTEE memory service. Some
// operations can take time, and we don't want to block the main thread as
// doing so could at the very least introduce a delay to shutting down
// concierge via SIGTERM.
base::Thread mms_thread_{"mms thread"};
// Put the socket after the thread so that it gets closed before the thread
// is join'ed. That will interrupt the thread if it is waiting, to ensure
// that it exists in a timely manner and doesn't block the dtor.
base::ScopedFD mms_socket_;
base::WeakPtrFactory<ManateeMemoryService> weak_ptr_factory_;
};
} // namespace concierge
} // namespace vm_tools
#endif // VM_TOOLS_CONCIERGE_MANATEE_MEMORY_SERVICE_H_