blob: fb04803a0d7373d4db4ce2018255fcb792b765ca [file] [log] [blame]
// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "android/emulation/DmaMap.h"
#include "android/base/containers/Lookup.h"
#include "android/base/memory/LazyInstance.h"
#include <type_traits>
#include <inttypes.h>
#include <stdio.h>
#define DEBUG 0
#if DEBUG >= 1
#define D(fmt,...) fprintf(stderr, "DmaMap: %s: " fmt "\n", __func__, ##__VA_ARGS__);
#else
#define D(...) (void)0
#endif
#if DEBUG >= 2
#define DD(fmt,...) fprintf(stderr, "DmaMap: %s: " fmt "\n", __func__, ##__VA_ARGS__);
#else
#define DD(...) (void)0
#endif
#define E(fmt,...) fprintf(stderr, "DmaMap: ERROR: %s: " fmt "\n", __func__, ##__VA_ARGS__);
namespace android {
static DmaMap* sInstance = nullptr;
DmaMap* DmaMap::get() {
return sInstance;
}
DmaMap* DmaMap::set(DmaMap* dmaMap) {
DmaMap* result = sInstance;
sInstance = dmaMap;
return result;
}
void DmaMap::addBuffer(void* hwpipe,
uint64_t guest_paddr,
uint64_t bufferSize) {
D("guest paddr 0x%llx bufferSize %llu",
(unsigned long long)guest_paddr,
(unsigned long long)bufferSize);
DmaBufferInfo info;
info.hwpipe = hwpipe;
info.guestAddr = guest_paddr; // guest address
info.bufferSize = bufferSize; // size of buffer
info.currHostAddr = kNullopt; // no current host address
android::base::AutoWriteLock lock(mLock);
createMappingLocked(&info);
mDmaBuffers[guest_paddr] = info;
}
void DmaMap::removeBuffer(uint64_t guest_paddr) {
D("guest paddr 0x%llx", (unsigned long long)guest_paddr);
android::base::AutoWriteLock lock(mLock);
if (auto info = android::base::find(mDmaBuffers, guest_paddr)) {
removeMappingLocked(info);
mDmaBuffers.erase(guest_paddr);
} else {
E("guest addr 0x%llx not alloced!",
(unsigned long long)guest_paddr);
}
}
void* DmaMap::getHostAddr(uint64_t guest_paddr) {
DD("guest paddr 0x%llx", (unsigned long long)guest_paddr);
android::base::AutoReadLock rlock(mLock);
if (auto info = android::base::find(mDmaBuffers, guest_paddr)) {
if (info->currHostAddr) {
DD("guest paddr 0x%llx -> host 0x%llx valid",
(unsigned long long)guest_paddr,
(unsigned long long)(*info->currHostAddr));
return *(info->currHostAddr);
} else {
rlock.unlockRead();
android::base::AutoWriteLock wlock(mLock);
createMappingLocked(info);
D("guest paddr 0x%llx -> host 0x%llx valid (new)",
(unsigned long long)guest_paddr,
(unsigned long long)*(info->currHostAddr));
return *(info->currHostAddr);
}
} else {
E("guest paddr 0x%llx not alloced!",
(unsigned long long)guest_paddr);
return 0;
}
}
void DmaMap::invalidateHostMappings() {
android::base::AutoWriteLock lock(mLock);
for (auto& it : mDmaBuffers) {
removeMappingLocked(&it.second);
}
}
void DmaMap::resetHostMappings() {
android::base::AutoWriteLock lock(mLock);
for (auto& it : mDmaBuffers) {
removeMappingLocked(&it.second);
}
mDmaBuffers.clear();
}
void* DmaMap::getPipeInstance(uint64_t guest_paddr) {
android::base::AutoReadLock lock(mLock);
if (auto info = android::base::find(mDmaBuffers, guest_paddr)) {
return info->hwpipe;
} else {
E("guest paddr 0x%llx not alloced!",
(unsigned long long)guest_paddr);
return nullptr;
}
}
void DmaMap::createMappingLocked(DmaBufferInfo* info) {
info->currHostAddr = doMap(info->guestAddr, info->bufferSize);
}
void DmaMap::removeMappingLocked(DmaBufferInfo* info ) {
if (info->currHostAddr) {
doUnmap(*(info->currHostAddr), info->bufferSize);
info->currHostAddr = kNullopt;
D("guest addr 0x%llx host mapping 0x%llx removed.",
(unsigned long long)info->guestAddr,
(unsigned long long)info->currHostAddr);
} else {
D("guest addr 0x%llx has no host mapping. don't remove.",
(unsigned long long)info->guestAddr);
}
}
} // namespace android