1/* 2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#ifndef __VIRTMMIO_H__ 16#define __VIRTMMIO_H__ 17 18/* NOTE: Only support non-legacy device and little-endian guest. */ 19 20#include "stdint.h" 21#include "los_reg.h" 22#include "stdbool.h" 23#include "los_arch_context.h" 24 25typedef unsigned long VADDR_T; 26typedef unsigned long PADDR_T; 27 28#define IO_DEVICE_ADDR(paddr) (paddr) 29#define VMM_TO_DMA_ADDR(vaddr) (vaddr) 30#define DMA_TO_VMM_ADDR(vaddr) (vaddr) 31#define IRQ_SPI_BASE RISCV_SYS_MAX_IRQ 32 33#define DSB dsb() 34#define FENCE_WRITE_UINT32(value, addr) ({ DSB; *((volatile UINT32 *)((UINTPTR)(addr))) = (value); }) 35 36uint64_t u32_to_u64(uint32_t addr); 37 38#define VIRTIO_STATUS_RESET 0 39#define VIRTIO_STATUS_ACK 1 40#define VIRTIO_STATUS_DRIVER 2 41#define VIRTIO_STATUS_DRIVER_OK 4 42#define VIRTIO_STATUS_FEATURES_OK 8 43#define VIRTIO_STATUS_DEVICE_NEEDS_RESET 64 44#define VIRTIO_STATUS_FAILED 128 45 46#define VIRTIO_FEATURE_WORD0 0 47#define VIRTIO_F_RING_INDIRECT_DESC (1 << 28) 48#define VIRTIO_FEATURE_WORD1 1 49#define VIRTIO_F_VERSION_1 (1 << 0) 50 51#define VIRTMMIO_REG_MAGICVALUE 0x00 52#define VIRTMMIO_REG_VERSION 0x04 53#define VIRTMMIO_REG_DEVICEID 0x08 54#define VIRTMMIO_REG_DEVFEATURE 0x10 55#define VIRTMMIO_REG_DEVFEATURESEL 0x14 56#define VIRTMMIO_REG_DRVFEATURE 0x20 57#define VIRTMMIO_REG_DRVFEATURESEL 0x24 58#define VIRTMMIO_REG_QUEUESEL 0x30 59#define VIRTMMIO_REG_QUEUENUMMAX 0x34 60#define VIRTMMIO_REG_QUEUENUM 0x38 61#define VIRTMMIO_REG_QUEUEREADY 0x44 62#define VIRTMMIO_REG_QUEUENOTIFY 0x50 63#define VIRTMMIO_REG_INTERRUPTSTATUS 0x60 64#define VIRTMMIO_REG_INTERRUPTACK 0x64 65#define VIRTMMIO_REG_STATUS 0x70 66#define VIRTMMIO_REG_QUEUEDESCLOW 0x80 67#define VIRTMMIO_REG_QUEUEDESCHIGH 0x84 68#define VIRTMMIO_REG_QUEUEDRIVERLOW 0x90 69#define VIRTMMIO_REG_QUEUEDRIVERHIGH 0x94 70#define VIRTMMIO_REG_QUEUEDEVICELOW 0xA0 71#define VIRTMMIO_REG_QUEUEDEVICEHIGH 0xA4 72#define VIRTMMIO_REG_CONFIGGENERATION 0xFC 73#define VIRTMMIO_REG_CONFIG 0x100 74 75#define VIRTQ_ALIGN_DESC 16 76#define VIRTQ_ALIGN_AVAIL 2 77#define VIRTQ_ALIGN_USED 4 78 79#define VIRTMMIO_MAGIC 0x74726976 80#define VIRTMMIO_VERSION 2 81#define VIRTMMIO_DEVICE_ID_NET 1 82#define VIRTMMIO_DEVICE_ID_GPU 16 83#define VIRTMMIO_DEVICE_ID_INPUT 18 84 85/* QEMU 5.2 virtio-mmio for riscv */ 86#define VIRTMMIO_BASE_ADDR 0x10001000 /* see hw/riscv/virt.c virt_memmap[] */ 87#define VIRTMMIO_BASE_SIZE 0x1000 /* see hw/riscv/virt.c virt_memmap[] */ 88#define VIRTMMIO_BASE_IRQ 1 /* see hw/riscv/virt.h VIRTIO_IRQ */ 89#define NUM_VIRTIO_TRANSPORTS 8 /* see hw/riscv/virt.h VIRTIO_COUNT */ 90 91#define VIRTMMIO_IRQ_NOTIFY_USED (1 << 0) 92 93struct VirtqDesc { 94 uint64_t pAddr; 95 uint32_t len; 96#define VIRTQ_DESC_F_NEXT (1 << 0) 97#define VIRTQ_DESC_F_WRITE (1 << 1) 98 uint16_t flag; 99 uint16_t next; 100}; 101 102struct VirtqAvail { 103#define VIRTQ_AVAIL_F_NO_INTERRUPT (1 << 0) 104 uint16_t flag; 105 uint16_t index; 106 uint16_t ring[]; 107 /* We do not use VIRTIO_F_EVENT_IDX, so no other member */ 108}; 109 110struct VirtqUsedElem { 111 uint32_t id; /* u32 for padding purpose */ 112 uint32_t len; 113}; 114 115struct VirtqUsed { 116#define VIRTQ_USED_F_NO_NOTIFY (1 << 0) 117 uint16_t flag; 118 uint16_t index; 119 struct VirtqUsedElem ring[]; 120 /* We do not use VIRTIO_F_EVENT_IDX, so no other member */ 121}; 122 123struct Virtq { 124 uint16_t qsz; 125 uint16_t last; 126 127 struct VirtqDesc *desc; 128 struct VirtqAvail *avail; 129 struct VirtqUsed *used; 130}; 131 132#define VIRTQ_NUM 2 133 134/* common virtio-mmio device structure, should be first member of specific device */ 135struct VirtmmioDev { 136 VADDR_T base; /* I/O base address */ 137#define _IRQ_MASK 0xFF /* higher bytes as registered flag */ 138 int irq; 139 struct Virtq vq[VIRTQ_NUM]; 140}; 141 142 143/* discover and fill in 'dev' if found given ID device */ 144bool VirtmmioDiscover(uint32_t devId, struct VirtmmioDev *dev); 145 146void VirtmmioInitBegin(const struct VirtmmioDev *dev); 147 148/* add 'supported'(default 0) according given 'features' */ 149typedef bool (*VirtioFeatureFn)(uint32_t features, uint32_t *supported, void *dev); 150 151/* negotiate 'baseDev' feature word 0 & 1 through 'f0' & 'f1'. 'dev' is passed to callbacks */ 152bool VirtmmioNegotiate(struct VirtmmioDev *baseDev, VirtioFeatureFn f0, VirtioFeatureFn f1, void *dev); 153 154/* calculate queue space of size 'qsz', conforming to alignment limits */ 155unsigned VirtqSize(uint16_t qsz); 156 157/* config pre-allocated continuous memory as two Virtq, started at 'base' with specified queue size */ 158VADDR_T VirtmmioConfigQueue(struct VirtmmioDev *dev, VADDR_T base, uint16_t qsz[], int num); 159 160bool VirtmmioRegisterIRQ(struct VirtmmioDev *dev, HWI_PROC_FUNC handle, void *argDev, const char *devName); 161 162void VritmmioInitEnd(const struct VirtmmioDev *dev); 163 164void VirtmmioInitFailed(const struct VirtmmioDev *dev); 165 166#endif 167