1// Copyright (C) 2019 The Android Open Source Project 2// Copyright (C) 2019 Google Inc. 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15 16#include <memory> 17#include <fcntl.h> 18#include <lib/zx/channel.h> 19#include <lib/zx/vmo.h> 20#include <log/log.h> 21#include <stdlib.h> 22#include <sys/stat.h> 23#include <sys/types.h> 24#include <unistd.h> 25#include <zircon/process.h> 26#include <zircon/syscalls.h> 27#include <zircon/syscalls/object.h> 28 29#include "goldfish_address_space.h" 30#include "android/base/synchronization/AndroidLock.h" 31#include "services/service_connector.h" 32 33#include <unordered_map> 34 35#define GET_STATUS_SAFE(result, member) \ 36 ((result).ok() ? ((result).Unwrap()->member) : ZX_OK) 37 38using android::base::guest::AutoLock; 39using android::base::guest::Lock; 40 41using llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriver; 42using llcpp::fuchsia::hardware::goldfish::AddressSpaceDevice; 43using llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriverType; 44using llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriverPingMessage; 45 46GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(GoldfishAddressSpaceSubdeviceType subdevice) { 47 48 if (subdevice != GoldfishAddressSpaceSubdeviceType::NoSubdevice) { 49 ALOGE("%s: Tried to use a nontrivial subdevice when support has not been added\n", __func__); 50 abort(); 51 } 52 53 zx::channel channel(GetConnectToServiceFunction()(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME)); 54 if (!channel) { 55 ALOGE("%s: failed to get service handle for " GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, 56 __FUNCTION__); 57 return; 58 } 59 m_device = std::make_unique<AddressSpaceDevice::SyncClient>(std::move(channel)); 60 61 zx::channel child_driver_server, child_driver_client; 62 zx_status_t status = zx::channel::create(0, &child_driver_server, &child_driver_client); 63 if (status != ZX_OK) { 64 ALOGE("%s: zx_channel_create failed: %d", __FUNCTION__, status); 65 return; 66 } 67 68 auto result = m_device->OpenChildDriver( 69 static_cast<AddressSpaceChildDriverType>(0 /* graphics */), 70 std::move(child_driver_server)); 71 if (!result.ok()) { 72 ALOGE("%s: failed to open child driver: %d", 73 __FUNCTION__, result.status()); 74 return; 75 } 76 m_child_driver = std::make_unique<AddressSpaceChildDriver::SyncClient>(std::move(child_driver_client)); 77} 78 79GoldfishAddressSpaceBlockProvider::~GoldfishAddressSpaceBlockProvider() 80{ 81} 82 83bool GoldfishAddressSpaceBlockProvider::is_opened() const 84{ 85 return !!m_device; 86} 87 88// void GoldfishAddressSpaceBlockProvider::close() - not implemented 89// address_space_handle_t GoldfishAddressSpaceBlockProvider::release() - not imeplemented 90 91GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock() 92 : m_driver(NULL) 93 , m_vmo(ZX_HANDLE_INVALID) 94 , m_mmaped_ptr(NULL) 95 , m_phys_addr(0) 96 , m_host_addr(0) 97 , m_offset(0) 98 , m_size(0) {} 99 100GoldfishAddressSpaceBlock::~GoldfishAddressSpaceBlock() 101{ 102 destroy(); 103} 104 105GoldfishAddressSpaceBlock &GoldfishAddressSpaceBlock::operator=(const GoldfishAddressSpaceBlock &rhs) 106{ 107 m_vmo = rhs.m_vmo; 108 m_mmaped_ptr = rhs.m_mmaped_ptr; 109 m_phys_addr = rhs.m_phys_addr; 110 m_host_addr = rhs.m_host_addr; 111 m_offset = rhs.m_offset; 112 m_size = rhs.m_size; 113 m_driver = rhs.m_driver; 114 115 return *this; 116} 117 118bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size) 119{ 120 ALOGD("%s: Ask for block of size 0x%llx\n", __func__, 121 (unsigned long long)size); 122 123 destroy(); 124 125 if (!provider->is_opened()) { 126 return false; 127 } 128 129 AddressSpaceChildDriver::SyncClient* driver = provider->m_child_driver.get(); 130 131 auto result = driver->AllocateBlock(size); 132 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 133 ALOGE("%s: allocate block failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res)); 134 return false; 135 } 136 m_phys_addr = result.Unwrap()->paddr; 137 m_vmo = result.Unwrap()->vmo.release(); 138 139 m_size = size; 140 m_offset = 0; 141 m_is_shared_mapping = false; 142 143 ALOGD("%s: allocate returned offset 0x%llx size 0x%llx\n", __func__, 144 (unsigned long long)m_offset, 145 (unsigned long long)m_size); 146 147 m_driver = driver; 148 return true; 149} 150 151bool GoldfishAddressSpaceBlock::claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size) 152{ 153 ALOGE("%s: FATAL: not supported\n", __func__); 154 abort(); 155} 156 157uint64_t GoldfishAddressSpaceBlock::physAddr() const 158{ 159 return m_phys_addr; 160} 161 162uint64_t GoldfishAddressSpaceBlock::hostAddr() const 163{ 164 return m_host_addr; 165} 166 167void *GoldfishAddressSpaceBlock::mmap(uint64_t host_addr) 168{ 169 if (m_size == 0) { 170 ALOGE("%s: called with zero size\n", __func__); 171 return NULL; 172 } 173 if (m_mmaped_ptr) { 174 ALOGE("'mmap' called for an already mmaped address block"); 175 ::abort(); 176 } 177 178 zx_vaddr_t ptr = 0; 179 zx_status_t status = zx_vmar_map(zx_vmar_root_self(), 180 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 181 0, m_vmo, 182 m_offset, 183 m_size, 184 &ptr); 185 if (status != ZX_OK) { 186 ALOGE("%s: host memory map failed with size 0x%llx " 187 "off 0x%llx status %d\n", 188 __func__, 189 (unsigned long long)m_size, 190 (unsigned long long)m_offset, status); 191 return NULL; 192 } 193 194 m_mmaped_ptr = (void*)ptr; 195 m_host_addr = host_addr; 196 return guestPtr(); 197} 198 199void *GoldfishAddressSpaceBlock::guestPtr() const 200{ 201 return reinterpret_cast<char *>(m_mmaped_ptr) + (m_host_addr & (PAGE_SIZE - 1)); 202} 203 204void GoldfishAddressSpaceBlock::destroy() 205{ 206 if (m_mmaped_ptr && m_size) { 207 zx_vmar_unmap(zx_vmar_root_self(), 208 (zx_vaddr_t)m_mmaped_ptr, 209 m_size); 210 m_mmaped_ptr = NULL; 211 } 212 213 if (m_size) { 214 zx_handle_close(m_vmo); 215 m_vmo = ZX_HANDLE_INVALID; 216 if (m_is_shared_mapping) { 217 // TODO 218 ALOGE("%s: unsupported: GoldfishAddressSpaceBlock destroy() for shared regions\n", __func__); 219 abort(); 220 // int32_t res = ZX_OK; 221 // auto result = m_driver->UnclaimShared(m_offset); 222 // if (!result.ok() || result.Unwrap()->res != ZX_OK) { 223 // ALOGE("%s: unclaim shared block failed: %d:%d", __func__, 224 // result.status(), GET_STATUS_SAFE(result, res)); 225 // } 226 } else { 227 auto result = m_driver->DeallocateBlock(m_phys_addr); 228 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 229 ALOGE("%s: deallocate block failed: %d:%d", __func__, 230 result.status(), GET_STATUS_SAFE(result, res)); 231 } 232 } 233 m_driver = NULL; 234 m_phys_addr = 0; 235 m_host_addr = 0; 236 m_offset = 0; 237 m_size = 0; 238 } 239} 240 241GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots) 242 : m_provider(GoldfishAddressSpaceSubdeviceType::HostMemoryAllocator) { } 243 244long GoldfishAddressSpaceHostMemoryAllocator::hostMalloc(GoldfishAddressSpaceBlock *block, size_t size) 245{ 246 return 0; 247} 248 249void GoldfishAddressSpaceHostMemoryAllocator::hostFree(GoldfishAddressSpaceBlock *block) 250{ 251} 252 253class VmoStore { 254public: 255 struct Info { 256 zx_handle_t vmo = ZX_HANDLE_INVALID; 257 uint64_t phys_addr = 0; 258 }; 259 260 void add(uint64_t offset, const Info& info) { 261 AutoLock lock(mLock); 262 mInfo[offset] = info; 263 } 264 265 void remove(uint64_t offset) { 266 AutoLock lock(mLock); 267 mInfo.erase(offset); 268 } 269 270 Info get(uint64_t offset) { 271 Info res; 272 AutoLock lock(mLock); 273 auto it = mInfo.find(offset); 274 if (it == mInfo.end()) { 275 ALOGE("VmoStore::%s cannot find info on offset 0x%llx\n", __func__, 276 (unsigned long long)offset); 277 return res; 278 } 279 res = it->second; 280 return res; 281 } 282 283private: 284 Lock mLock; 285 std::unordered_map<uint64_t, Info> mInfo; 286}; 287 288static Lock sVmoStoreInitLock; 289static VmoStore* sVmoStore = nullptr; 290 291static VmoStore* getVmoStore() { 292 AutoLock lock(sVmoStoreInitLock); 293 if (!sVmoStore) sVmoStore = new VmoStore; 294 return sVmoStore; 295} 296 297address_space_handle_t goldfish_address_space_open() { 298 zx::channel channel(GetConnectToServiceFunction()(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME)); 299 if (!channel) { 300 ALOGE("%s: failed to get service handle for " GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, 301 __FUNCTION__); 302 return 0; 303 } 304 AddressSpaceDevice::SyncClient* 305 deviceSync = new AddressSpaceDevice::SyncClient(std::move(channel)); 306 return (address_space_handle_t)deviceSync; 307} 308 309void goldfish_address_space_close(address_space_handle_t handle) { 310 AddressSpaceDevice::SyncClient* deviceSync = 311 reinterpret_cast< 312 AddressSpaceDevice::SyncClient*>(handle); 313 delete deviceSync; 314} 315 316bool goldfish_address_space_set_subdevice_type( 317 address_space_handle_t handle, GoldfishAddressSpaceSubdeviceType type, 318 address_space_handle_t* handle_out) { 319 320 AddressSpaceDevice::SyncClient* deviceSync = 321 reinterpret_cast< 322 AddressSpaceDevice::SyncClient*>(handle); 323 324 zx::channel child_driver_server, child_driver_client; 325 zx_status_t status = zx::channel::create(0, &child_driver_server, &child_driver_client); 326 if (status != ZX_OK) { 327 ALOGE("%s: zx_channel_create failed: %d", __FUNCTION__, status); 328 return false; 329 } 330 331 deviceSync->OpenChildDriver( 332 static_cast<AddressSpaceChildDriverType>(type), 333 std::move(child_driver_server)); 334 335 AddressSpaceChildDriver::SyncClient* 336 childSync = new AddressSpaceChildDriver::SyncClient(std::move(child_driver_client)); 337 338 // On creating a subdevice, in our use cases we wont be needing the 339 // original device sync anymore, so get rid of it. 340 delete deviceSync; 341 342 *handle_out = (void*)childSync; 343 344 return true; 345} 346 347bool goldfish_address_space_allocate( 348 address_space_handle_t handle, 349 size_t size, uint64_t* phys_addr, uint64_t* offset) { 350 AddressSpaceChildDriver::SyncClient* deviceSync = 351 reinterpret_cast< 352 AddressSpaceChildDriver::SyncClient*>(handle); 353 354 zx::vmo vmo; 355 auto result = deviceSync->AllocateBlock(size); 356 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 357 ALOGE("%s: allocate block failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res)); 358 return false; 359 } 360 *phys_addr = result.Unwrap()->paddr; 361 vmo = std::move(result.Unwrap()->vmo); 362 363 *offset = 0; 364 365 VmoStore::Info info = { 366 vmo.release(), 367 *phys_addr, 368 }; 369 370 getVmoStore()->add(*offset, info); 371 return true; 372} 373 374bool goldfish_address_space_free( 375 address_space_handle_t handle, uint64_t offset) { 376 auto info = getVmoStore()->get(offset); 377 if (info.vmo == ZX_HANDLE_INVALID) return false; 378 zx_handle_close(info.vmo); 379 380 AddressSpaceChildDriver::SyncClient* deviceSync = 381 reinterpret_cast< 382 AddressSpaceChildDriver::SyncClient*>(handle); 383 384 auto result = deviceSync->DeallocateBlock(info.phys_addr); 385 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 386 ALOGE("%s: deallocate block failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res)); 387 return false; 388 } 389 390 return true; 391} 392 393bool goldfish_address_space_claim_shared( 394 address_space_handle_t handle, uint64_t offset, uint64_t size) { 395 396 AddressSpaceChildDriver::SyncClient* deviceSync = 397 reinterpret_cast< 398 AddressSpaceChildDriver::SyncClient*>(handle); 399 400 zx::vmo vmo; 401 auto result = deviceSync->ClaimSharedBlock(offset, size); 402 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 403 ALOGE("%s: claim shared failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res)); 404 return false; 405 } 406 vmo = std::move(result.Unwrap()->vmo); 407 408 VmoStore::Info info = { 409 vmo.release(), 410 }; 411 412 getVmoStore()->add(offset, info); 413 414 return true; 415} 416 417bool goldfish_address_space_unclaim_shared( 418 address_space_handle_t handle, uint64_t offset) { 419 AddressSpaceChildDriver::SyncClient* deviceSync = 420 reinterpret_cast< 421 AddressSpaceChildDriver::SyncClient*>(handle); 422 423 auto result = deviceSync->UnclaimSharedBlock(offset); 424 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 425 ALOGE("%s: unclaim shared failed: %d:%d", __func__, result.status(), GET_STATUS_SAFE(result, res)); 426 return false; 427 } 428 429 getVmoStore()->remove(offset); 430 return true; 431} 432 433// pgoff is the offset into the page to return in the result 434void* goldfish_address_space_map( 435 address_space_handle_t handle, 436 uint64_t offset, uint64_t size, 437 uint64_t pgoff) { 438 439 auto info = getVmoStore()->get(offset); 440 if (info.vmo == ZX_HANDLE_INVALID) return nullptr; 441 442 zx_vaddr_t ptr = 0; 443 zx_status_t status = 444 zx_vmar_map(zx_vmar_root_self(), 445 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 446 0, info.vmo, 447 0, size, 448 &ptr); 449 return (void*)(((char*)ptr) + (uintptr_t)(pgoff & (PAGE_SIZE - 1))); 450} 451 452void goldfish_address_space_unmap(void* ptr, uint64_t size) { 453 zx_vmar_unmap(zx_vmar_root_self(), 454 (zx_vaddr_t)(((uintptr_t)ptr) & (uintptr_t)(~(PAGE_SIZE - 1))), 455 size); 456} 457 458bool goldfish_address_space_ping( 459 address_space_handle_t handle, 460 struct address_space_ping* ping) { 461 462 AddressSpaceChildDriverPingMessage fuchsiaPing = 463 *(AddressSpaceChildDriverPingMessage*)ping; 464 465 AddressSpaceChildDriver::SyncClient* deviceSync = 466 reinterpret_cast< 467 AddressSpaceChildDriver::SyncClient*>(handle); 468 469 AddressSpaceChildDriverPingMessage res; 470 auto result = deviceSync->Ping(fuchsiaPing); 471 if (!result.ok() || result.Unwrap()->res != ZX_OK) { 472 return false; 473 } 474 res = std::move(result.Unwrap()->ping); 475 476 *ping = *(struct address_space_ping*)(&res); 477 return true; 478} 479