VirtIO.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <Kernel/VirtIO/VirtIO.h>
  27. namespace Kernel {
  28. void VirtIO::detect()
  29. {
  30. PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
  31. if (address.is_null() || id.is_null())
  32. return;
  33. if (id.vendor_id != VIRTIO_PCI_VENDOR_ID)
  34. return;
  35. });
  36. }
  37. VirtIODevice::VirtIODevice(PCI::Address address, const char* class_name)
  38. : PCI::Device(address, PCI::get_interrupt_line(address))
  39. , m_class_name(class_name)
  40. , m_io_base(IOAddress(PCI::get_BAR0(pci_address()) & ~1))
  41. {
  42. dbgln("{}: Found @ {}", m_class_name, pci_address());
  43. enable_bus_mastering(pci_address());
  44. reset_device();
  45. set_status_bit(DEVICE_STATUS_ACKNOWLEDGE);
  46. auto capabilities = PCI::get_physical_id(address).capabilities();
  47. for (auto& capability : capabilities) {
  48. if (capability.id() == PCI_CAPABILITY_VENDOR_SPECIFIC) {
  49. // We have a virtio_pci_cap
  50. Configuration cfg = {};
  51. cfg.cfg_type = capability.read8(0x3);
  52. switch (cfg.cfg_type) {
  53. case VIRTIO_PCI_CAP_COMMON_CFG:
  54. case VIRTIO_PCI_CAP_NOTIFY_CFG:
  55. case VIRTIO_PCI_CAP_ISR_CFG:
  56. case VIRTIO_PCI_CAP_DEVICE_CFG:
  57. case VIRTIO_PCI_CAP_PCI_CFG: {
  58. auto cap_length = capability.read8(0x2);
  59. if (cap_length < 0x10) {
  60. dbgln("{}: Unexpected capability size: {}", m_class_name, cap_length);
  61. break;
  62. }
  63. cfg.bar = capability.read8(0x4);
  64. if (cfg.bar > 0x5) {
  65. dbgln("{}: Unexpected capability bar value: {}", m_class_name, cfg.bar);
  66. break;
  67. }
  68. cfg.offset = capability.read32(0x8);
  69. cfg.length = capability.read32(0xc);
  70. dbgln_if(VIRTIO_DEBUG, "{}: Found configuration {}, bar: {}, offset: {}, length: {}", m_class_name, cfg.cfg_type, cfg.bar, cfg.offset, cfg.length);
  71. m_configs.append(cfg);
  72. if (cfg.cfg_type == VIRTIO_PCI_CAP_COMMON_CFG)
  73. m_use_mmio = true;
  74. else if (cfg.cfg_type == VIRTIO_PCI_CAP_NOTIFY_CFG)
  75. m_notify_multiplier = capability.read32(0x10);
  76. break;
  77. }
  78. default:
  79. dbgln("{}: Unknown capability configuration type: {}", m_class_name, cfg.cfg_type);
  80. break;
  81. }
  82. }
  83. }
  84. m_common_cfg = get_config(VIRTIO_PCI_CAP_COMMON_CFG, 0);
  85. m_notify_cfg = get_config(VIRTIO_PCI_CAP_NOTIFY_CFG, 0);
  86. m_isr_cfg = get_config(VIRTIO_PCI_CAP_ISR_CFG, 0);
  87. set_status_bit(DEVICE_STATUS_DRIVER);
  88. }
  89. VirtIODevice::~VirtIODevice()
  90. {
  91. }
  92. auto VirtIODevice::mapping_for_bar(u8 bar) -> MappedMMIO&
  93. {
  94. VERIFY(m_use_mmio);
  95. auto& mapping = m_mmio[bar];
  96. if (!mapping.base) {
  97. mapping.size = PCI::get_BAR_space_size(pci_address(), bar);
  98. mapping.base = MM.allocate_kernel_region(PhysicalAddress(page_base_of(PCI::get_BAR(pci_address(), bar))), page_round_up(mapping.size), "VirtIO MMIO", Region::Access::Read | Region::Access::Write, Region::Cacheable::No);
  99. if (!mapping.base)
  100. dbgln("{}: Failed to map bar {}", m_class_name, bar);
  101. }
  102. return mapping;
  103. }
  104. void VirtIODevice::notify_queue(u16 queue_index)
  105. {
  106. dbgln("VirtIODevice: notifying about queue change at idx: {}", queue_index);
  107. if (!m_use_mmio)
  108. out<u16>(REG_QUEUE_NOTIFY, queue_index);
  109. else
  110. config_write16(m_notify_cfg, get_queue(queue_index)->notify_offset() * m_notify_multiplier, queue_index);
  111. }
  112. u8 VirtIODevice::config_read8(const Configuration* config, u32 offset)
  113. {
  114. return mapping_for_bar(config->bar).read<u8>(config->offset + offset);
  115. }
  116. u16 VirtIODevice::config_read16(const Configuration* config, u32 offset)
  117. {
  118. return mapping_for_bar(config->bar).read<u16>(config->offset + offset);
  119. }
  120. u32 VirtIODevice::config_read32(const Configuration* config, u32 offset)
  121. {
  122. return mapping_for_bar(config->bar).read<u32>(config->offset + offset);
  123. }
  124. void VirtIODevice::config_write8(const Configuration* config, u32 offset, u8 value)
  125. {
  126. mapping_for_bar(config->bar).write(config->offset + offset, value);
  127. }
  128. void VirtIODevice::config_write16(const Configuration* config, u32 offset, u16 value)
  129. {
  130. mapping_for_bar(config->bar).write(config->offset + offset, value);
  131. }
  132. void VirtIODevice::config_write32(const Configuration* config, u32 offset, u32 value)
  133. {
  134. mapping_for_bar(config->bar).write(config->offset + offset, value);
  135. }
  136. void VirtIODevice::config_write64(const Configuration* config, u32 offset, u64 value)
  137. {
  138. mapping_for_bar(config->bar).write(config->offset + offset, value);
  139. }
  140. u8 VirtIODevice::read_status_bits()
  141. {
  142. if (!m_use_mmio)
  143. return in<u8>(REG_DEVICE_STATUS);
  144. return config_read8(m_common_cfg, COMMON_CFG_DEVICE_STATUS);
  145. }
  146. void VirtIODevice::clear_status_bit(u8 status_bit)
  147. {
  148. m_status &= status_bit;
  149. if (!m_use_mmio)
  150. out<u8>(REG_DEVICE_STATUS, m_status);
  151. else
  152. config_write8(m_common_cfg, COMMON_CFG_DEVICE_STATUS, m_status);
  153. }
  154. void VirtIODevice::set_status_bit(u8 status_bit)
  155. {
  156. m_status |= status_bit;
  157. if (!m_use_mmio)
  158. out<u8>(REG_DEVICE_STATUS, m_status);
  159. else
  160. config_write8(m_common_cfg, COMMON_CFG_DEVICE_STATUS, m_status);
  161. }
  162. u64 VirtIODevice::get_device_features()
  163. {
  164. if (!m_use_mmio)
  165. return in<u32>(REG_DEVICE_FEATURES);
  166. config_write32(m_common_cfg, COMMON_CFG_DEVICE_FEATURE_SELECT, 0);
  167. auto lower_bits = config_read32(m_common_cfg, COMMON_CFG_DEVICE_FEATURE);
  168. config_write32(m_common_cfg, COMMON_CFG_DEVICE_FEATURE_SELECT, 1);
  169. u64 upper_bits = (u64)config_read32(m_common_cfg, COMMON_CFG_DEVICE_FEATURE) << 32;
  170. return upper_bits | lower_bits;
  171. }
  172. bool VirtIODevice::accept_device_features(u64 device_features, u64 accepted_features)
  173. {
  174. VERIFY(!m_did_accept_features);
  175. m_did_accept_features = true;
  176. if (is_feature_set(device_features, VIRTIO_F_VERSION_1)) {
  177. accepted_features |= VIRTIO_F_VERSION_1;
  178. } else {
  179. dbgln("{}: legacy device detected", m_class_name);
  180. }
  181. if (is_feature_set(device_features, VIRTIO_F_RING_PACKED)) {
  182. dbgln("{}: packed queues not yet supported", m_class_name);
  183. accepted_features &= ~(VIRTIO_F_RING_PACKED);
  184. }
  185. dbgln("VirtIOConsole: Device features: {}", device_features);
  186. dbgln("VirtIOConsole: Accepted features: {}", accepted_features);
  187. if (!m_use_mmio) {
  188. out<u32>(REG_GUEST_FEATURES, accepted_features);
  189. } else {
  190. config_write32(m_common_cfg, COMMON_CFG_DRIVER_FEATURE_SELECT, 0);
  191. config_write32(m_common_cfg, COMMON_CFG_DRIVER_FEATURE, accepted_features);
  192. config_write32(m_common_cfg, COMMON_CFG_DRIVER_FEATURE_SELECT, 1);
  193. config_write32(m_common_cfg, COMMON_CFG_DRIVER_FEATURE, accepted_features >> 32);
  194. }
  195. set_status_bit(DEVICE_STATUS_FEATURES_OK);
  196. m_status = read_status_bits();
  197. if (!(m_status & DEVICE_STATUS_FEATURES_OK)) {
  198. set_status_bit(DEVICE_STATUS_FAILED);
  199. dbgln("{}: Features not accepted by host!", m_class_name);
  200. return false;
  201. }
  202. m_accepted_features = accepted_features;
  203. dbgln_if(VIRTIO_DEBUG, "{}: Features accepted by host", m_class_name);
  204. return true;
  205. }
  206. auto VirtIODevice::get_common_config(u32 index) const -> const Configuration*
  207. {
  208. if (index == 0)
  209. return m_common_cfg;
  210. return get_config(VIRTIO_PCI_CAP_COMMON_CFG, index);
  211. }
  212. auto VirtIODevice::get_device_config(u32 index) const -> const Configuration*
  213. {
  214. return get_config(VIRTIO_PCI_CAP_DEVICE_CFG, index);
  215. }
  216. void VirtIODevice::reset_device()
  217. {
  218. dbgln_if(VIRTIO_DEBUG, "{}: Reset device", m_class_name);
  219. if (!m_use_mmio) {
  220. clear_status_bit(0);
  221. while (read_status_bits() != 0) {
  222. // TODO: delay a bit?
  223. }
  224. return;
  225. } else if (m_common_cfg) {
  226. config_write8(m_common_cfg, COMMON_CFG_DEVICE_STATUS, 0);
  227. while (config_read8(m_common_cfg, COMMON_CFG_DEVICE_STATUS) != 0) {
  228. // TODO: delay a bit?
  229. }
  230. return;
  231. }
  232. dbgln_if(VIRTIO_DEBUG, "{}: No handle to device, cant reset", m_class_name);
  233. }
  234. bool VirtIODevice::setup_queue(u16 queue_index)
  235. {
  236. if (!m_use_mmio || !m_common_cfg)
  237. return false;
  238. config_write16(m_common_cfg, COMMON_CFG_QUEUE_SELECT, queue_index);
  239. u16 queue_size = config_read16(m_common_cfg, COMMON_CFG_QUEUE_SIZE);
  240. if (queue_size == 0) {
  241. dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] is unavailable!", m_class_name, queue_index);
  242. return true;
  243. }
  244. u16 queue_notify_offset = config_read16(m_common_cfg, COMMON_CFG_QUEUE_NOTIFY_OFF);
  245. auto queue = make<VirtIOQueue>(queue_size, queue_notify_offset);
  246. if (queue->is_null())
  247. return false;
  248. config_write64(m_common_cfg, COMMON_CFG_QUEUE_DESC, queue->descriptor_area().get());
  249. config_write64(m_common_cfg, COMMON_CFG_QUEUE_DRIVER, queue->driver_area().get());
  250. config_write64(m_common_cfg, COMMON_CFG_QUEUE_DEVICE, queue->device_area().get());
  251. dbgln_if(VIRTIO_DEBUG, "{}: Queue[{}] size: {}", m_class_name, queue_index, queue_size);
  252. m_queues.append(move(queue));
  253. return true;
  254. }
  255. void VirtIODevice::set_requested_queue_count(u16 count)
  256. {
  257. m_queue_count = count;
  258. }
  259. bool VirtIODevice::setup_queues()
  260. {
  261. if (m_common_cfg) {
  262. auto maximum_queue_count = config_read16(m_common_cfg, COMMON_CFG_NUM_QUEUES);
  263. if (m_queue_count == 0) {
  264. m_queue_count = maximum_queue_count;
  265. } else if (m_queue_count > maximum_queue_count) {
  266. dbgln("{}: {} queues requested but only {} available!", m_class_name, m_queue_count, maximum_queue_count);
  267. return false;
  268. }
  269. }
  270. dbgln_if(VIRTIO_DEBUG, "{}: Setting up {} queues", m_class_name, m_queue_count);
  271. for (u16 i = 0; i < m_queue_count; i++) {
  272. if (!setup_queue(i))
  273. return false;
  274. }
  275. return true;
  276. }
  277. bool VirtIODevice::finish_init()
  278. {
  279. VERIFY(m_did_accept_features);
  280. VERIFY(!(m_status & DEVICE_STATUS_DRIVER_OK));
  281. if (!setup_queues()) {
  282. dbgln("{}: Failed to setup queues", m_class_name);
  283. return false;
  284. }
  285. set_status_bit(DEVICE_STATUS_DRIVER_OK);
  286. dbgln_if(VIRTIO_DEBUG, "{}: Finished initialization", m_class_name);
  287. return true;
  288. }
  289. void VirtIODevice::supply_buffer_and_notify(u16 queue_index, const u8* buffer, u32 len, BufferType buffer_type)
  290. {
  291. VERIFY(queue_index < m_queue_count);
  292. if (get_queue(queue_index)->supply_buffer(buffer, len, buffer_type))
  293. notify_queue(queue_index);
  294. }
  295. u8 VirtIODevice::isr_status()
  296. {
  297. if (!m_use_mmio)
  298. return in<u8>(REG_ISR_STATUS);
  299. return config_read8(m_isr_cfg, 0);
  300. }
  301. void VirtIODevice::handle_irq(const RegisterState&)
  302. {
  303. u8 isr_type = isr_status();
  304. dbgln_if(VIRTIO_DEBUG, "VirtIODevice: Handling interrupt with status: {}", isr_type);
  305. if (isr_type & DEVICE_CONFIG_INTERRUPT)
  306. handle_device_config_change();
  307. if (isr_type & QUEUE_INTERRUPT) {
  308. for (auto& queue : m_queues) {
  309. if (queue.handle_interrupt())
  310. return;
  311. }
  312. }
  313. }
  314. }