/* SPDX-License-Identifier: (GPL-2.0 OR CDDL-1.0) */ /* * vboxguest core guest-device handling code, VBoxGuest.cpp in upstream svn. * * Copyright (C) 2007-2016 Oracle Corporation */ #include <linux/device.h> #include <linux/io.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/sizes.h> #include <linux/slab.h> #include <linux/vbox_err.h> #include <linux/vbox_utils.h> #include <linux/vmalloc.h> #include "vboxguest_core.h" #include "vboxguest_version.h" /* Get the pointer to the first HGCM parameter. */ #define VBG_IOCTL_HGCM_CALL_PARMS(a) … /* Get the pointer to the first HGCM parameter in a 32-bit request. */ #define VBG_IOCTL_HGCM_CALL_PARMS32(a) … #define GUEST_MAPPINGS_TRIES … #define VBG_KERNEL_REQUEST … /** * vbg_guest_mappings_init - Reserves memory in which the VMM can * relocate any guest mappings that are floating around. * @gdev: The Guest extension device. * * This operation is a little bit tricky since the VMM might not accept * just any address because of address clashes between the three contexts * it operates in, so we try several times. * * Failure to reserve the guest mappings is ignored. */ static void vbg_guest_mappings_init(struct vbg_dev *gdev) { … } /** * vbg_guest_mappings_exit - Undo what vbg_guest_mappings_init did. * * @gdev: The Guest extension device. */ static void vbg_guest_mappings_exit(struct vbg_dev *gdev) { … } /** * vbg_report_guest_info - Report the guest information to the host. * @gdev: The Guest extension device. * * Return: %0 or negative errno value. */ static int vbg_report_guest_info(struct vbg_dev *gdev) { … } /** * vbg_report_driver_status - Report the guest driver status to the host. * @gdev: The Guest extension device. * @active: Flag whether the driver is now active or not. * * Return: 0 or negative errno value. */ static int vbg_report_driver_status(struct vbg_dev *gdev, bool active) { … } /** * vbg_balloon_inflate - Inflate the balloon by one chunk. The caller * owns the balloon mutex. * @gdev: The Guest extension device. * @chunk_idx: Index of the chunk. * * Return: %0 or negative errno value. */ static int vbg_balloon_inflate(struct vbg_dev *gdev, u32 chunk_idx) { … } /** * vbg_balloon_deflate - Deflate the balloon by one chunk. The caller * owns the balloon mutex. * @gdev: The Guest extension device. * @chunk_idx: Index of the chunk. * * Return: %0 or negative errno value. */ static int vbg_balloon_deflate(struct vbg_dev *gdev, u32 chunk_idx) { … } /* * Respond to VMMDEV_EVENT_BALLOON_CHANGE_REQUEST events, query the size * the host wants the balloon to be and adjust accordingly. */ static void vbg_balloon_work(struct work_struct *work) { … } /* * Callback for heartbeat timer. */ static void vbg_heartbeat_timer(struct timer_list *t) { … } /** * vbg_heartbeat_host_config - Configure the host to check guest's heartbeat * and get heartbeat interval from the host. * @gdev: The Guest extension device. * @enabled: Set true to enable guest heartbeat checks on host. * * Return: %0 or negative errno value. */ static int vbg_heartbeat_host_config(struct vbg_dev *gdev, bool enabled) { … } /** * vbg_heartbeat_init - Initializes the heartbeat timer. This feature * may be disabled by the host. * @gdev: The Guest extension device. * * Return: %0 or negative errno value. */ static int vbg_heartbeat_init(struct vbg_dev *gdev) { … } /** * vbg_heartbeat_exit - Cleanup heartbeat code, stop HB timer and disable * host heartbeat checking. * @gdev: The Guest extension device. */ static void vbg_heartbeat_exit(struct vbg_dev *gdev) { … } /** * vbg_track_bit_usage - Applies a change to the bit usage tracker. * @tracker: The bit usage tracker. * @changed: The bits to change. * @previous: The previous value of the bits. * * Return: %true if the mask changed, %false if not. */ static bool vbg_track_bit_usage(struct vbg_bit_usage_tracker *tracker, u32 changed, u32 previous) { … } /** * vbg_reset_host_event_filter - Init and termination worker for * resetting the (host) event filter on the host * @gdev: The Guest extension device. * @fixed_events: Fixed events (init time). * * Return: %0 or negative errno value. */ static int vbg_reset_host_event_filter(struct vbg_dev *gdev, u32 fixed_events) { … } /** * vbg_set_session_event_filter - Changes the event filter mask for the * given session. * @gdev: The Guest extension device. * @session: The session. * @or_mask: The events to add. * @not_mask: The events to remove. * @session_termination: Set if we're called by the session cleanup code. * This tweaks the error handling so we perform * proper session cleanup even if the host * misbehaves. * * This is called in response to VBG_IOCTL_CHANGE_FILTER_MASK as well as to * do session cleanup. Takes the session mutex. * * Return: 0 or negative errno value. */ static int vbg_set_session_event_filter(struct vbg_dev *gdev, struct vbg_session *session, u32 or_mask, u32 not_mask, bool session_termination) { … } /** * vbg_reset_host_capabilities - Init and termination worker for set * guest capabilities to zero on the host. * @gdev: The Guest extension device. * * Return: %0 or negative errno value. */ static int vbg_reset_host_capabilities(struct vbg_dev *gdev) { … } /** * vbg_set_host_capabilities - Set guest capabilities on the host. * @gdev: The Guest extension device. * @session: The session. * @session_termination: Set if we're called by the session cleanup code. * * Must be called with gdev->session_mutex hold. * * Return: %0 or negative errno value. */ static int vbg_set_host_capabilities(struct vbg_dev *gdev, struct vbg_session *session, bool session_termination) { … } /** * vbg_acquire_session_capabilities - Acquire (get exclusive access) * guest capabilities for a session. * @gdev: The Guest extension device. * @session: The session. * @flags: Flags (VBGL_IOC_AGC_FLAGS_XXX). * @or_mask: The capabilities to add. * @not_mask: The capabilities to remove. * @session_termination: Set if we're called by the session cleanup code. * This tweaks the error handling so we perform * proper session cleanup even if the host * misbehaves. * * Takes the session mutex. * * Return: %0 or negative errno value. */ static int vbg_acquire_session_capabilities(struct vbg_dev *gdev, struct vbg_session *session, u32 or_mask, u32 not_mask, u32 flags, bool session_termination) { … } /** * vbg_set_session_capabilities - Sets the guest capabilities for a * session. Takes the session mutex. * @gdev: The Guest extension device. * @session: The session. * @or_mask: The capabilities to add. * @not_mask: The capabilities to remove. * @session_termination: Set if we're called by the session cleanup code. * This tweaks the error handling so we perform * proper session cleanup even if the host * misbehaves. * * Return: %0 or negative errno value. */ static int vbg_set_session_capabilities(struct vbg_dev *gdev, struct vbg_session *session, u32 or_mask, u32 not_mask, bool session_termination) { … } /** * vbg_query_host_version - get the host feature mask and version information. * @gdev: The Guest extension device. * * Return: %0 or negative errno value. */ static int vbg_query_host_version(struct vbg_dev *gdev) { … } /** * vbg_core_init - Initializes the VBoxGuest device extension when the * device driver is loaded. * @gdev: The Guest extension device. * @fixed_events: Events that will be enabled upon init and no client * will ever be allowed to mask. * * The native code locates the VMMDev on the PCI bus and retrieve * the MMIO and I/O port ranges, this function will take care of * mapping the MMIO memory (if present). Upon successful return * the native code should set up the interrupt handler. * * Return: %0 or negative errno value. */ int vbg_core_init(struct vbg_dev *gdev, u32 fixed_events) { … } /** * vbg_core_exit - Call this on exit to clean-up vboxguest-core managed * resources. * @gdev: The Guest extension device. * * The native code should call this before the driver is loaded, * but don't call this on shutdown. */ void vbg_core_exit(struct vbg_dev *gdev) { … } /** * vbg_core_open_session - Creates a VBoxGuest user session. * @gdev: The Guest extension device. * @requestor: VMMDEV_REQUESTOR_* flags * * vboxguest_linux.c calls this when userspace opens the char-device. * * Return: A pointer to the new session or an ERR_PTR on error. */ struct vbg_session *vbg_core_open_session(struct vbg_dev *gdev, u32 requestor) { … } /** * vbg_core_close_session - Closes a VBoxGuest session. * @session: The session to close (and free). */ void vbg_core_close_session(struct vbg_session *session) { … } static int vbg_ioctl_chk(struct vbg_ioctl_hdr *hdr, size_t in_size, size_t out_size) { … } static int vbg_ioctl_driver_version_info( struct vbg_ioctl_driver_version_info *info) { … } /* Must be called with the event_lock held */ static u32 vbg_get_allowed_event_mask_for_session(struct vbg_dev *gdev, struct vbg_session *session) { … } static bool vbg_wait_event_cond(struct vbg_dev *gdev, struct vbg_session *session, u32 event_mask) { … } /* Must be called with the event_lock held */ static u32 vbg_consume_events_locked(struct vbg_dev *gdev, struct vbg_session *session, u32 event_mask) { … } static int vbg_ioctl_wait_for_events(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_wait_for_events *wait) { … } static int vbg_ioctl_interrupt_all_wait_events(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_hdr *hdr) { … } /** * vbg_req_allowed - Checks if the VMM request is allowed in the * context of the given session. * @gdev: The Guest extension device. * @session: The calling session. * @req: The request. * * Return: %0 or negative errno value. */ static int vbg_req_allowed(struct vbg_dev *gdev, struct vbg_session *session, const struct vmmdev_request_header *req) { … } static int vbg_ioctl_vmmrequest(struct vbg_dev *gdev, struct vbg_session *session, void *data) { … } static int vbg_ioctl_hgcm_connect(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_hgcm_connect *conn) { … } static int vbg_ioctl_hgcm_disconnect(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_hgcm_disconnect *disconn) { … } static bool vbg_param_valid(enum vmmdev_hgcm_function_parameter_type type) { … } static int vbg_ioctl_hgcm_call(struct vbg_dev *gdev, struct vbg_session *session, bool f32bit, struct vbg_ioctl_hgcm_call *call) { … } static int vbg_ioctl_log(struct vbg_ioctl_log *log) { … } static int vbg_ioctl_change_filter_mask(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_change_filter *filter) { … } static int vbg_ioctl_acquire_guest_capabilities(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_acquire_guest_caps *caps) { … } static int vbg_ioctl_change_guest_capabilities(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_set_guest_caps *caps) { … } static int vbg_ioctl_check_balloon(struct vbg_dev *gdev, struct vbg_ioctl_check_balloon *balloon_info) { … } static int vbg_ioctl_write_core_dump(struct vbg_dev *gdev, struct vbg_session *session, struct vbg_ioctl_write_coredump *dump) { … } /** * vbg_core_ioctl - Common IOCtl for user to kernel communication. * @session: The client session. * @req: The requested function. * @data: The i/o data buffer, minimum size sizeof(struct vbg_ioctl_hdr). * * Return: %0 or negative errno value. */ int vbg_core_ioctl(struct vbg_session *session, unsigned int req, void *data) { … } /** * vbg_core_set_mouse_status - Report guest supported mouse-features to the host. * * @gdev: The Guest extension device. * @features: The set of features to report to the host. * * Return: %0 or negative errno value. */ int vbg_core_set_mouse_status(struct vbg_dev *gdev, u32 features) { … } /* Core interrupt service routine. */ irqreturn_t vbg_core_isr(int irq, void *dev_id) { … }