1/* 2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6#pragma once 7 8/*** 9 * @module ioports.h 10 * The ioports interface provides a useful abstraction for initialising, registering and handling ioport events 11 * for a guest VM instance. This is independent from the x86 libsel4vm ioports interface. This interface is intended 12 * to be more generic and architecture independent, useful for usecases that require ioports without architecture 13 * support (virtio PCI). 14 */ 15 16#include <stdlib.h> 17#include <stdint.h> 18#include <stdbool.h> 19 20typedef int (*ioport_in_fn)(void *cookie, unsigned int port_no, unsigned int size, unsigned int *result); 21typedef int (*ioport_out_fn)(void *cookie, unsigned int port_no, unsigned int size, unsigned int value); 22 23typedef enum ioport_type { 24 IOPORT_FREE, 25 IOPORT_ADDR 26} ioport_type_t; 27 28/*** 29 * @struct ioport_range 30 * Range of ioport handler 31 * @param {uint16_t} start Start address of ioport range 32 * @param {uint16_t} end End address of ioport range 33 * @param {uint16_t} size Size of ioport range 34 */ 35typedef struct ioport_range { 36 uint16_t start; 37 uint16_t end; 38 uint16_t size; 39} ioport_range_t; 40 41/*** 42 * @struct ioport_interface 43 * Datastructure used for ioport emulation, containing handlers for the ioport range 44 * @param {void *} cookie User supplied cookie to pass onto handlers 45 * @param {ioport_in_fn} port_in IO in operation handler 46 * @param {ioport_out_fn} port_out IO out operation handler 47 * @param {const char *} desc IOPort description, useful for debugging 48 */ 49typedef struct ioport_interface { 50 void *cookie; 51 ioport_in_fn port_in; 52 ioport_out_fn port_out; 53 const char *desc; 54} ioport_interface_t; 55 56/*** 57 * @struct ioport_entry 58 * Datastructure used to present a registered ioport range 59 * @param {ioport_range_t} range IO address range of ioport entry 60 * @param {ioport_interface_t} interface Emulation interface for ioport range 61 */ 62typedef struct ioport_entry { 63 ioport_range_t range; 64 ioport_interface_t interface; 65} ioport_entry_t; 66 67/*** 68 * @struct vmm_io_list 69 * Parent datastructure used to maintain a list of registered ioports 70 * @param {int} num_ioports Total number of registered ioports 71 * @param {ioport_entry_t **} List of registered ioport objects 72 * @param {uint16_t} alloc_addr Base ioport address we can safely bump allocate from, used when registering ioport handlers of type 'IOPORT_FREE' 73 */ 74typedef struct vmm_io_list { 75 int num_ioports; 76 /* Sorted list of ioport functions */ 77 ioport_entry_t **ioports; 78 uint16_t alloc_addr; 79} vmm_io_port_list_t; 80 81/*** 82 * @function vmm_io_port_init(io_list, ioport_alloc_addr) 83 * Initialize the io port list manager. 84 * @param {vmm_io_port_list_t **} io_list Pointer to io_port list handle. This will be allocated and initialised 85 * @param {uint16_t} ioport_alloc_addr Base ioport address we can safely bump allocate from (doesn't conflict with other ioports). 86 * This is used when registering ioport handlers of type 'IOPORT_FREE' 87 * @return 0 for success, otherwise -1 for error 88 */ 89int vmm_io_port_init(vmm_io_port_list_t **io_list, uint16_t ioport_alloc_addr); 90 91/*** 92 * @function vmm_io_port_add_handler(io_list, ioport_range, ioport_interface, port_type) 93 * Add an io port range for emulation 94 * @param {vmm_io_port_list_t *} io_list Handle to ioport list. This is where the new ioport handler will be appended to 95 * @param {ioport_range_t} ioport_range Range the ioport handler will emulate 96 * @param {ioport_interface_t} ioport_interface IOPort emulation interface 97 * @param {ioport_type_t} port_type The type of ioport being registered - IOPORT_FREE, IOPORT_ADDR 98 * @return NULL for error, otherwise pointer to newly created ioport entry 99 */ 100ioport_entry_t *vmm_io_port_add_handler(vmm_io_port_list_t *io_list, ioport_range_t ioport_range, 101 ioport_interface_t ioport_interface, ioport_type_t port_type); 102 103/*** 104 * @function emulate_io_handler(io_port, port_no, is_in, size, data) 105 * From a set of registered ioports, emulate an io instruction given a current ioport access. 106 * @param {vmm_io_port_list_t *} io_port List of registered ioports with in/out handlers 107 * @param {unsigned int} port_no IOPort address being accessed 108 * @param {bool} is_in True if we are performing an io in operation, otherwise False 109 * @param {size_t} size Size of io access 110 * @param {unsigned int *} data Pointer with the data being written if io-out op, otherwise will be populated with data from an io-in op 111 * @return 0 if handled, 1 if unhandled, otherwise -1 for error 112 */ 113int emulate_io_handler(vmm_io_port_list_t *io_port, unsigned int port_no, bool is_in, size_t size, unsigned int *data); 114