Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions accel/tcg/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@
#include "tcg/tcg.h"
#include "library.h"
#include "fileutils.h"
#include "bridge_private.h"
void *getAlternate(void *addr);
#include "bridge.h"
extern struct elfheader_s * elf_header;
#endif
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
Expand Down Expand Up @@ -195,8 +194,10 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
#ifdef CONFIG_LATX_KZT
Dl_info dl_info;
if (latx_kzt_runtime_enabled() && itb->pc > reserved_va &&
dladdr ((const void *)((onebridge_t *)itb->pc)->f, &dl_info)) {
uintptr_t function;
if (latx_kzt_runtime_enabled() &&
kzt_registered_onebridge_snapshot(itb->pc, NULL, &function) &&
dladdr((const void *)function, &dl_info)) {
qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
"pid(%d) - tid(%" PRIuPTR ") Trace cpu%d: %p [ "
TARGET_FMT_lx "/%#x] KZT:%s\n",
Expand Down
5 changes: 0 additions & 5 deletions accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -3816,11 +3816,6 @@ void *page_alloc_target_data(target_ulong address, size_t size)

bool page_check_range(target_ulong start, target_ulong len, int flags)
{
#if defined(CONFIG_LATX_KZT)
if (latx_kzt_runtime_enabled() && start > reserved_va) {
return true;
}
#endif
target_ulong last;
int locked; /* tri-state: =0: unlocked, +1: global, -1: local */
bool ret;
Expand Down
21 changes: 19 additions & 2 deletions accel/tcg/user-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#include "latx-options.h"
#include "latx-backtrace.h"
#include "latx-smc.h"
#if defined(CONFIG_LATX_KZT)
#include "bridge.h"
#include "wrappertbbridge.h"
#endif
#endif
#ifdef CONFIG_LATX_DEBUG
#include "latx-debug.h"
Expand Down Expand Up @@ -724,8 +728,21 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
g_assert_not_reached();
}

if (!guest_addr_valid_untagged(addr) ||
!page_check_range(addr, 1, flags)) {
bool valid = guest_addr_valid_untagged(addr) &&
page_check_range(addr, 1, flags);

#if defined(CONFIG_LATX_KZT)
if (!valid && latx_kzt_runtime_enabled()) {
if (access_type == MMU_INST_FETCH) {
valid = kzt_is_registered_onebridge(addr) ||
kzt_tbbridge_contains(addr);
} else if (!guest_addr_valid_untagged(addr)) {
valid = kzt_data_addr_valid_untagged(addr);
}
}
#endif

if (!valid) {
if (nonfault) {
return TLB_INVALID_MASK;
} else {
Expand Down
36 changes: 28 additions & 8 deletions include/exec/cpu_ldst.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

#if defined(CONFIG_LATX_KZT)
#include "kzt-runtime.h"
#include "kzt-address-policy.h"
#endif
#if defined(CONFIG_USER_ONLY)
/* sparc32plus has 64bit long but 32bit space address
Expand Down Expand Up @@ -93,23 +94,42 @@ static inline void *g2h(CPUState *cs, abi_ptr x)
static inline bool guest_addr_valid_untagged(abi_ulong x)
{
#if defined(CONFIG_LATX_KZT)
if (latx_kzt_runtime_enabled()) {
return true;
} else
#endif
return kzt_guest_addr_is_valid(x, GUEST_ADDR_MAX);
#else
return x <= GUEST_ADDR_MAX;
#endif
}

static inline bool guest_range_valid_untagged(abi_ulong start, abi_ulong len)
{
#if defined(CONFIG_LATX_KZT)
if (latx_kzt_runtime_enabled()) {
return true;
} else
#endif
return kzt_guest_range_is_valid(start, len, GUEST_ADDR_MAX);
#else
return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
#endif
}

#if defined(CONFIG_LATX_KZT)
/*
* KZT wrappers may expose host-owned objects to translated code. Keep that
* compatibility permission separate from the guest virtual-address policy:
* callers which create, remove, or protect guest mappings must continue to
* use guest_addr_valid_untagged() and guest_range_valid_untagged().
*/
static inline bool kzt_data_addr_valid_untagged(abi_ulong addr)
{
return kzt_data_addr_is_valid(latx_kzt_runtime_enabled(), addr,
GUEST_ADDR_MAX);
}

static inline bool kzt_data_range_valid_untagged(abi_ulong start,
abi_ulong len)
{
return kzt_data_range_is_valid(latx_kzt_runtime_enabled(), start, len,
GUEST_ADDR_MAX);
}
#endif

#define h2g_valid(x) \
(HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS || \
(uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX)
Expand Down
17 changes: 17 additions & 0 deletions linux-user/qemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -638,11 +638,28 @@ extern unsigned long vir_rlimit_as_acc;

static inline bool access_ok_untagged(int type, abi_ulong addr, abi_ulong size)
{
#if defined(CONFIG_LATX_KZT)
bool guest_range = size == 0
? guest_addr_valid_untagged(addr)
: guest_range_valid_untagged(addr, size);

if (size == 0
? !kzt_data_addr_valid_untagged(addr)
: !kzt_data_range_valid_untagged(addr, size)) {
return false;
}

/* Native wrapper objects do not have entries in the guest page map. */
if (!guest_range) {
return true;
}
#else
if (size == 0
? !guest_addr_valid_untagged(addr)
: !guest_range_valid_untagged(addr, size)) {
return false;
}
#endif
return page_check_range((target_ulong)addr, size, type);
}

Expand Down
98 changes: 95 additions & 3 deletions target/i386/latx/context/bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,46 @@ typedef struct brick_s {
onebridge_t *b;
int sz;
brick_t *next;
brick_t *registry_next;
} brick_t;

typedef struct bridge_s {
brick_t *head;
brick_t *last; // to speed up
kh_bridgemap_t *bridgemap;
GMutex lock;
} bridge_t;

static GMutex bridge_registry_lock;
static brick_t *bridge_registry;

static void register_brick(brick_t *brick)
{
if (brick->b == MAP_FAILED) {
return;
}

g_mutex_lock(&bridge_registry_lock);
brick->registry_next = bridge_registry;
bridge_registry = brick;
g_mutex_unlock(&bridge_registry_lock);
}

static void unregister_brick(brick_t *brick)
{
brick_t **link;

g_mutex_lock(&bridge_registry_lock);
for (link = &bridge_registry; *link; link = &(*link)->registry_next) {
if (*link == brick) {
*link = brick->registry_next;
break;
}
}
brick->registry_next = NULL;
g_mutex_unlock(&bridge_registry_lock);
}

//from wrapped/wrappedlibc.c
//void* my_mmap(x64emu_t* emu, void* addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
//int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
Expand All @@ -50,12 +82,14 @@ brick_t* NewBrick(void)
printf("Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t));
}
ret->b = ptr;
register_brick(ret);
return ret;
}

bridge_t *NewBridge(void)
{
bridge_t *b = (bridge_t*)box_calloc(1, sizeof(bridge_t));
g_mutex_init(&b->lock);
b->head = NewBrick();
b->last = b->head;
b->bridgemap = kh_init(bridgemap);
Expand All @@ -66,14 +100,18 @@ void FreeBridge(bridge_t** bridge)
{
if(!bridge || !*bridge)
return;
g_mutex_lock(&(*bridge)->lock);
brick_t *b = (*bridge)->head;
while(b) {
brick_t *n = b->next;
unregister_brick(b);
munmap(b->b, NBRICK*sizeof(onebridge_t));
box_free(b);
b = n;
}
kh_destroy(bridgemap, (*bridge)->bridgemap);
g_mutex_unlock(&(*bridge)->lock);
g_mutex_clear(&(*bridge)->lock);
box_free(*bridge);
*bridge = NULL;
}
Expand All @@ -82,35 +120,89 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
{
brick_t *b = NULL;
int sz = -1;
g_mutex_lock(&bridge->lock);
b = bridge->last;
if(b->sz == NBRICK) {
b->next = NewBrick();
b = b->next;
bridge->last = b;
}
sz = b->sz;
b->sz++;
g_mutex_lock(&bridge_registry_lock);
b->b[sz].CC = 0xCC;
b->b[sz].S = 'S'; b->b[sz].C='C';
b->b[sz].w = w;
b->b[sz].f = (uintptr_t)fnc;
b->b[sz].C3 = N?0xC2:0xC3;
b->b[sz].N = N;
b->sz++;
g_mutex_unlock(&bridge_registry_lock);
// add bridge to map, for fast recovery
int ret;
khint_t k = kh_put(bridgemap, bridge->bridgemap, (uintptr_t)fnc, &ret);
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;

g_mutex_unlock(&bridge->lock);
return (uintptr_t)&b->b[sz].CC;
}

static onebridge_t *find_registered_onebridge(uintptr_t addr)
{
for (brick_t *brick = bridge_registry; brick;
brick = brick->registry_next) {
uintptr_t start = (uintptr_t)brick->b;
uintptr_t used_end = start + brick->sz * sizeof(onebridge_t);

if (addr >= start && addr < used_end &&
(addr - start) % sizeof(onebridge_t) == 0) {
onebridge_t *slot = (onebridge_t *)addr;

return slot->CC == 0xCC && slot->S == 'S' && slot->C == 'C' &&
(slot->C3 == 0xC3 || slot->C3 == 0xC2) ? slot : NULL;
}
}

return NULL;
}

bool kzt_is_registered_onebridge(uintptr_t addr)
{
g_mutex_lock(&bridge_registry_lock);
bool found = find_registered_onebridge(addr) != NULL;
g_mutex_unlock(&bridge_registry_lock);
return found;
}

bool kzt_registered_onebridge_snapshot(uintptr_t addr, wrapper_t *wrapper,
uintptr_t *function)
{
g_mutex_lock(&bridge_registry_lock);
onebridge_t *slot = find_registered_onebridge(addr);

if (slot) {
if (wrapper) {
*wrapper = slot->w;
}
if (function) {
*function = slot->f;
}
}
g_mutex_unlock(&bridge_registry_lock);
return slot != NULL;
}

uintptr_t CheckBridged(bridge_t* bridge, void* fnc)
{
// check if function alread have a bridge (the function wrapper will not be tested)
g_mutex_lock(&bridge->lock);
khint_t k = kh_get(bridgemap, bridge->bridgemap, (uintptr_t)fnc);
if(k==kh_end(bridge->bridgemap))
if (k == kh_end(bridge->bridgemap)) {
g_mutex_unlock(&bridge->lock);
return 0;
return kh_value(bridge->bridgemap, k);
}
uintptr_t ret = kh_value(bridge->bridgemap, k);
g_mutex_unlock(&bridge->lock);
return ret;
}

uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name)
Expand Down
14 changes: 11 additions & 3 deletions target/i386/latx/context/wrappertbbridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,23 @@ void* kzt_tbbridge_init(void)
}
struct kzt_tbbridge* kzt_tbbridge_lookup(target_ulong pc)
{
lsassert(tree&&pc);
if (!pc) {
return NULL;
}
struct kzt_tbbridge key = {.pc = pc};
g_mutex_lock(&tree_lock);
struct kzt_tbbridge *bridge =
(struct kzt_tbbridge *)g_tree_lookup(tree, &key);
struct kzt_tbbridge *bridge = tree
? (struct kzt_tbbridge *)g_tree_lookup(tree, &key)
: NULL;
g_mutex_unlock(&tree_lock);
return bridge;
}

bool kzt_tbbridge_contains(target_ulong pc)
{
return kzt_tbbridge_lookup(pc) != NULL;
}

int kzt_tbbridge_insert(target_ulong pc, ADDR func, void * wrapper)
{
lsassert(tree&&pc&&wrapper);
Expand Down
3 changes: 3 additions & 0 deletions target/i386/latx/include/bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t AddAutomaticBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
bool kzt_is_registered_onebridge(uintptr_t addr);
bool kzt_registered_onebridge_snapshot(uintptr_t addr, wrapper_t *wrapper,
uintptr_t *function);
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);

Expand Down
Loading