diff mbox series

libpdbg: Run hwp only if target is enabled and hwp is defined

Message ID 20200625014135.206576-1-amitay@ozlabs.org
State New
Headers show
Series libpdbg: Run hwp only if target is enabled and hwp is defined | expand

Commit Message

Amitay Isaacs June 25, 2020, 1:41 a.m. UTC
Signed-off-by: Amitay Isaacs <amitay@ozlabs.org>
---
 libpdbg/adu.c    |  42 ++++++++++
 libpdbg/htm.c    |  44 +++++++++-
 libpdbg/target.c | 111 +++++++++++++++++++++++++
 libpdbg/thread.c | 210 ++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 391 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/libpdbg/adu.c b/libpdbg/adu.c
index 6600caa..6358e7a 100644
--- a/libpdbg/adu.c
+++ b/libpdbg/adu.c
@@ -118,6 +118,11 @@  static int adu_read(struct mem *adu, uint64_t start_addr, uint8_t *output,
 	int rc = 0;
 	uint64_t addr0, addr;
 
+	if (!adu->getmem) {
+		PR_ERROR("getmem() not implemented for the target\n");
+		return -1;
+	}
+
 	if (!block_size)
 		block_size = 8;
 
@@ -167,6 +172,10 @@  int adu_getmem(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_read(adu, start_addr, output, size, 8, false);
@@ -178,6 +187,10 @@  int adu_getmem_ci(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_read(adu, start_addr, output, size, 8, true);
@@ -189,6 +202,10 @@  int adu_getmem_io(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	/* There is no equivalent for cachable memory as blocksize
@@ -202,6 +219,10 @@  int __adu_getmem(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_read(adu, start_addr, output, size, 8, ci);
@@ -213,6 +234,11 @@  static int adu_write(struct mem *adu, uint64_t start_addr, uint8_t *input,
 	int rc = 0, tsize;
 	uint64_t addr, data, end_addr;
 
+	if (!adu->putmem) {
+		PR_ERROR("putmem() not implemented for the target\n");
+		return -1;
+	}
+
 	if (!block_size)
 		block_size = 8;
 
@@ -251,6 +277,10 @@  int adu_putmem(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_write(adu, start_addr, input, size, 8, false);
@@ -262,6 +292,10 @@  int adu_putmem_ci(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_write(adu, start_addr, input, size, 8, true);
@@ -273,6 +307,10 @@  int adu_putmem_io(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_write(adu, start_addr, input, size, block_size, true);
@@ -284,6 +322,10 @@  int __adu_putmem(struct pdbg_target *adu_target, uint64_t start_addr,
 	struct mem *adu;
 
 	assert(pdbg_target_is_class(adu_target, "mem"));
+
+	if (pdbg_target_status(adu_target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	adu = target_to_mem(adu_target);
 
 	return adu_write(adu, start_addr, input, size, 8, ci);
diff --git a/libpdbg/htm.c b/libpdbg/htm.c
index a259478..0d755dd 100644
--- a/libpdbg/htm.c
+++ b/libpdbg/htm.c
@@ -171,11 +171,13 @@  struct htm_status {
 
 static struct htm *check_and_convert(struct pdbg_target *target)
 {
-
 	if (!pdbg_target_is_class(target, "nhtm") &&
 	    !pdbg_target_is_class(target, "chtm"))
 	    return NULL;
 
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return NULL;
+
 	return target_to_htm(target);
 }
 
@@ -183,21 +185,45 @@  int htm_start(struct pdbg_target *target)
 {
 	struct htm *htm = check_and_convert(target);
 
-	return htm ? htm->start(htm) : -1;
+	if (!htm)
+		return -1;
+
+	if (!htm->start) {
+		PR_ERROR("start() not implemented for the target\n");
+		return -1;
+	}
+
+	return htm->start(htm);
 }
 
 int htm_stop(struct pdbg_target *target)
 {
 	struct htm *htm = check_and_convert(target);
 
-	return htm ? htm->stop(htm) : -1;
+	if (!htm)
+		return -1;
+
+	if (!htm->stop) {
+		PR_ERROR("stop() not implemented for the target\n");
+		return -1;
+	}
+
+	return htm->stop(htm);
 }
 
 int htm_status(struct pdbg_target *target)
 {
 	struct htm *htm = check_and_convert(target);
 
-	return htm ? htm->status(htm) : -1;
+	if (!htm)
+		return -1;
+
+	if (!htm->status) {
+		PR_ERROR("status() not implemented for the target\n");
+		return -1;
+	}
+
+	return htm->status(htm);
 }
 
 int htm_dump(struct pdbg_target *target, char *filename)
@@ -207,6 +233,11 @@  int htm_dump(struct pdbg_target *target, char *filename)
 	if (!htm || !filename)
 		return -1;
 
+	if (!htm->dump) {
+		PR_ERROR("dump() not implemented for the target\n");
+		return -1;
+	}
+
 	return htm->dump(htm, filename);
 }
 
@@ -217,6 +248,11 @@  int htm_record(struct pdbg_target *target, char *filename)
 	if (!htm || !filename)
 		return -1;
 
+	if (!htm->record) {
+		PR_ERROR("record() not implemented for the target\n");
+		return -1;
+	}
+
 	return htm->record(htm, filename);
 }
 
diff --git a/libpdbg/target.c b/libpdbg/target.c
index 99bce92..728c535 100644
--- a/libpdbg/target.c
+++ b/libpdbg/target.c
@@ -132,8 +132,17 @@  int pib_read(struct pdbg_target *pib_dt, uint64_t addr, uint64_t *data)
 	uint64_t target_addr = addr;
 	int rc;
 
+	if (pdbg_target_status(pib_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	pib_dt = get_class_target_addr(pib_dt, "pib", &target_addr);
 	pib = target_to_pib(pib_dt);
+
+	if (!pib->read) {
+		PR_ERROR("read() not implemented for the target\n");
+		return -1;
+	}
+
 	if (target_addr & PPC_BIT(0))
 		rc = pib_indirect_read(pib, target_addr, data);
 	else
@@ -151,8 +160,17 @@  int pib_write(struct pdbg_target *pib_dt, uint64_t addr, uint64_t data)
 	uint64_t target_addr = addr;
 	int rc;
 
+	if (pdbg_target_status(pib_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	pib_dt = get_class_target_addr(pib_dt, "pib", &target_addr);
 	pib = target_to_pib(pib_dt);
+
+	if (!pib->write) {
+		PR_ERROR("write() not implemented for the target\n");
+		return -1;
+	}
+
 	PR_DEBUG("addr:0x%08" PRIx64 " data:0x%016" PRIx64 "\n",
 		 target_addr, data);
 	if (target_addr & PPC_BIT(0))
@@ -171,6 +189,9 @@  int pib_write_mask(struct pdbg_target *pib_dt, uint64_t addr, uint64_t data, uin
 	uint64_t value;
 	int rc;
 
+	if (pdbg_target_status(pib_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	rc = pib_read(pib_dt, addr, &value);
 	if (rc)
 		return rc;
@@ -187,9 +208,17 @@  int pib_wait(struct pdbg_target *pib_dt, uint64_t addr, uint64_t mask, uint64_t
 	uint64_t tmp;
 	int rc;
 
+	if (pdbg_target_status(pib_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	pib_dt = get_class_target_addr(pib_dt, "pib", &addr);
 	pib = target_to_pib(pib_dt);
 
+	if (!pib->read) {
+		PR_ERROR("read() not implemented for the target\n");
+		return -1;
+	}
+
 	do {
 		if (addr & PPC_BIT(0))
 			rc = pib_indirect_read(pib, addr, &tmp);
@@ -207,8 +236,17 @@  int opb_read(struct pdbg_target *opb_dt, uint32_t addr, uint32_t *data)
 	struct opb *opb;
 	uint64_t addr64 = addr;
 
+	if (pdbg_target_status(opb_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	opb_dt = get_class_target_addr(opb_dt, "opb", &addr64);
 	opb = target_to_opb(opb_dt);
+
+	if (!opb->read) {
+		PR_ERROR("read() not implemented for the target\n");
+		return -1;
+	}
+
 	return opb->read(opb, addr64, data);
 }
 
@@ -217,9 +255,16 @@  int opb_write(struct pdbg_target *opb_dt, uint32_t addr, uint32_t data)
 	struct opb *opb;
 	uint64_t addr64 = addr;
 
+	if (pdbg_target_status(opb_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	opb_dt = get_class_target_addr(opb_dt, "opb", &addr64);
 	opb = target_to_opb(opb_dt);
 
+	if (!opb->write) {
+		PR_ERROR("write() not implemented for the target\n");
+		return -1;
+	}
 	return opb->write(opb, addr64, data);
 }
 
@@ -229,9 +274,17 @@  int fsi_read(struct pdbg_target *fsi_dt, uint32_t addr, uint32_t *data)
 	int rc;
 	uint64_t addr64 = addr;
 
+	if (pdbg_target_status(fsi_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	fsi_dt = get_class_target_addr(fsi_dt, "fsi", &addr64);
 	fsi = target_to_fsi(fsi_dt);
 
+	if (!fsi->read) {
+		PR_ERROR("read() not implemented for the target\n");
+		return -1;
+	}
+
 	rc = fsi->read(fsi, addr64, data);
 	PR_DEBUG("rc = %d, addr = 0x%05" PRIx64 ", data = 0x%08" PRIx32 ", target = %s\n",
 		 rc, addr64, *data, pdbg_target_path(&fsi->target));
@@ -244,9 +297,17 @@  int fsi_write(struct pdbg_target *fsi_dt, uint32_t addr, uint32_t data)
 	int rc;
 	uint64_t addr64 = addr;
 
+	if (pdbg_target_status(fsi_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	fsi_dt = get_class_target_addr(fsi_dt, "fsi", &addr64);
 	fsi = target_to_fsi(fsi_dt);
 
+	if (!fsi->write) {
+		PR_ERROR("write() not implemented for the target\n");
+		return -1;
+	}
+
 	rc = fsi->write(fsi, addr64, data);
 	PR_DEBUG("rc = %d, addr = 0x%05" PRIx64 ", data = 0x%08" PRIx32 ", target = %s\n",
 		 rc, addr64, data, pdbg_target_path(&fsi->target));
@@ -258,6 +319,9 @@  int fsi_write_mask(struct pdbg_target *fsi_dt, uint32_t addr, uint32_t data, uin
 	uint32_t value;
 	int rc;
 
+	if (pdbg_target_status(fsi_dt) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	rc = fsi_read(fsi_dt, addr, &value);
 	if (rc)
 		return rc;
@@ -274,7 +338,16 @@  int mem_read(struct pdbg_target *target, uint64_t addr, uint8_t *output, uint64_
 
 	assert(pdbg_target_is_class(target, "mem"));
 
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	mem = target_to_mem(target);
+
+	if (!mem->read) {
+		PR_ERROR("read() not implemented for the target\n");
+		return -1;
+	}
+
 	rc = mem->read(mem, addr, output, size, block_size, ci);
 
 	return rc;
@@ -287,7 +360,16 @@  int mem_write(struct pdbg_target *target, uint64_t addr, uint8_t *input, uint64_
 
 	assert(pdbg_target_is_class(target, "mem"));
 
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	mem = target_to_mem(target);
+
+	if (!mem->write) {
+		PR_ERROR("write() not implemented for the target\n");
+		return -1;
+	}
+
 	rc = mem->write(mem, addr, input, size, block_size, ci);
 
 	return rc;
@@ -299,6 +381,10 @@  struct chipop *pib_to_chipop(struct pdbg_target *pib)
 	uint32_t index;
 
 	assert(pdbg_target_is_class(pib, "pib"));
+
+	if (pdbg_target_status(pib) != PDBG_TARGET_ENABLED)
+		return NULL;
+
 	index = pdbg_target_index(pib);
 
 	pdbg_for_each_class_target("chipop", chipop) {
@@ -320,6 +406,11 @@  int sbe_istep(struct pdbg_target *target, uint32_t major, uint32_t minor)
 	if (!chipop)
 		return -1;
 
+	if (!chipop->istep) {
+		PR_ERROR("istep() not implemented for the target\n");
+		return -1;
+	}
+
 	return chipop->istep(chipop, major, minor);
 }
 
@@ -331,6 +422,11 @@  int sbe_mpipl_enter(struct pdbg_target *target)
 	if (!chipop)
 		return -1;
 
+	if (!chipop->mpipl_enter) {
+		PR_ERROR("mpipl_enter() not implemented for the target\n");
+		return -1;
+	}
+
 	return chipop->mpipl_enter(chipop);
 }
 
@@ -342,6 +438,11 @@  int sbe_mpipl_continue(struct pdbg_target *target)
 	if (!chipop)
 		return -1;
 
+	if (!chipop->mpipl_continue) {
+		PR_ERROR("mpipl_continue() not implemented for the target\n");
+		return -1;
+	}
+
 	return chipop->mpipl_continue(chipop);
 }
 
@@ -353,6 +454,11 @@  int sbe_mpipl_get_ti_info(struct pdbg_target *target, uint8_t **data, uint32_t *
 	if (!chipop)
 		return -1;
 
+	if (!chipop->mpipl_get_ti_info) {
+		PR_ERROR("mpipl_get_ti_info() not implemented for the target\n");
+		return -1;
+	}
+
 	return chipop->mpipl_get_ti_info(chipop, data, data_len);
 }
 
@@ -364,6 +470,11 @@  uint32_t sbe_ffdc_get(struct pdbg_target *target, const uint8_t **ffdc, uint32_t
 	if (!chipop)
 		return -1;
 
+	if (!chipop->ffdc_get) {
+		PR_ERROR("ffdc_get() not implemented for the target\n");
+		return -1;
+	}
+
 	return chipop->ffdc_get(chipop, ffdc, ffdc_len);
 }
 
diff --git a/libpdbg/thread.c b/libpdbg/thread.c
index 193efb2..e494dbc 100644
--- a/libpdbg/thread.c
+++ b/libpdbg/thread.c
@@ -36,7 +36,17 @@  int thread_step(struct pdbg_target *target, int count)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
+
+	if (!thread->step) {
+		PR_ERROR("step() not implemented for the target\n");
+		return -1;
+	}
+
 	return thread->step(thread, count);
 }
 
@@ -45,7 +55,17 @@  int thread_start(struct pdbg_target *target)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
+
+	if (!thread->start) {
+		PR_ERROR("start() not implemented for the target\n");
+		return -1;
+	}
+
 	return thread->start(thread);
 }
 
@@ -54,7 +74,17 @@  int thread_stop(struct pdbg_target *target)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
+
+	if (!thread->stop) {
+		PR_ERROR("stop() not implemented for the target\n");
+		return -1;
+	}
+
 	return thread->stop(thread);
 }
 
@@ -63,7 +93,17 @@  int thread_sreset(struct pdbg_target *target)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
+
+	if (!thread->sreset) {
+		PR_ERROR("sreset() not implemented for the target\n");
+		return -1;
+	}
+
 	return thread->sreset(thread);
 }
 
@@ -75,6 +115,9 @@  int thread_step_all(void)
 	pdbg_for_each_class_target("pib", target) {
 		struct pib *pib = target_to_pib(target);
 
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
 		if (!pib->thread_step_all)
 			break;
 
@@ -90,9 +133,13 @@  int thread_step_all(void)
 			continue;
 
 		rc |= thread_step(thread, 1);
+		count++;
 	}
 
-	return rc;
+	if (count > 0)
+		return rc;
+
+	return -1;
 }
 
 int thread_start_all(void)
@@ -103,6 +150,9 @@  int thread_start_all(void)
 	pdbg_for_each_class_target("pib", target) {
 		struct pib *pib = target_to_pib(target);
 
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
 		if (!pib->thread_start_all)
 			break;
 
@@ -118,9 +168,13 @@  int thread_start_all(void)
 			continue;
 
 		rc |= thread_start(thread);
+		count++;
 	}
 
-	return rc;
+	if (count > 0)
+		return rc;
+
+	return -1;
 }
 
 int thread_stop_all(void)
@@ -131,6 +185,9 @@  int thread_stop_all(void)
 	pdbg_for_each_class_target("pib", target) {
 		struct pib *pib = target_to_pib(target);
 
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
 		if (!pib->thread_stop_all)
 			break;
 
@@ -146,9 +203,13 @@  int thread_stop_all(void)
 			continue;
 
 		rc |= thread_stop(thread);
+		count++;
 	}
 
-	return rc;
+	if (count > 0)
+		return rc;
+
+	return -1;
 }
 
 int thread_sreset_all(void)
@@ -159,6 +220,9 @@  int thread_sreset_all(void)
 	pdbg_for_each_class_target("pib", target) {
 		struct pib *pib = target_to_pib(target);
 
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
 		if (!pib->thread_sreset_all)
 			break;
 
@@ -174,9 +238,13 @@  int thread_sreset_all(void)
 			continue;
 
 		rc |= thread_sreset(thread);
+		count++;
 	}
 
-	return rc;
+	if (count > 0)
+		return rc;
+
+	return -1;
 }
 
 int thread_getmem(struct pdbg_target *target, uint64_t addr, uint64_t *value)
@@ -184,13 +252,18 @@  int thread_getmem(struct pdbg_target *target, uint64_t addr, uint64_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
-	if (thread->getmem)
-		return thread->getmem(thread, addr, value);
+	if (!thread->getmem) {
+		PR_ERROR("getmem() not imeplemented for the target\n");
+		return -1;
+	}
 
-	PR_ERROR("Not implemented on the backend\n");
-	return -1;
+	return thread->getmem(thread, addr, value);
 }
 
 int thread_getregs(struct pdbg_target *target, struct thread_regs *regs)
@@ -198,13 +271,18 @@  int thread_getregs(struct pdbg_target *target, struct thread_regs *regs)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
-	if (thread->getregs)
-		return thread->getregs(thread, regs);
+	if (!thread->getregs) {
+		PR_ERROR("getregs() not imeplemented for the target\n");
+		return -1;
+	}
 
-	PR_ERROR("Not implemented on the backend\n");
-	return -1;
+	return thread->getregs(thread, regs);
 }
 
 int thread_getgpr(struct pdbg_target *target, int gpr, uint64_t *value)
@@ -212,8 +290,17 @@  int thread_getgpr(struct pdbg_target *target, int gpr, uint64_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->getgpr) {
+		PR_ERROR("getgpr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->getgpr(thread, gpr, value);
 }
 
@@ -222,8 +309,17 @@  int thread_putgpr(struct pdbg_target *target, int gpr, uint64_t value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->putgpr) {
+		PR_ERROR("putgpr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->putgpr(thread, gpr, value);
 }
 
@@ -232,8 +328,17 @@  int thread_getspr(struct pdbg_target *target, int spr, uint64_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->getspr) {
+		PR_ERROR("getspr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->getspr(thread, spr, value);
 }
 
@@ -242,8 +347,17 @@  int thread_putspr(struct pdbg_target *target, int spr, uint64_t value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->putspr) {
+		PR_ERROR("putspr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->putspr(thread, spr, value);
 }
 
@@ -252,8 +366,17 @@  int thread_getmsr(struct pdbg_target *target, uint64_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->getmsr) {
+		PR_ERROR("getmsr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->getmsr(thread, value);
 }
 
@@ -262,8 +385,17 @@  int thread_putmsr(struct pdbg_target *target, uint64_t value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->putmsr) {
+		PR_ERROR("putmsr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->putmsr(thread, value);
 }
 
@@ -272,8 +404,17 @@  int thread_getnia(struct pdbg_target *target, uint64_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->getnia) {
+		PR_ERROR("getnia() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->getnia(thread, value);
 }
 
@@ -282,8 +423,17 @@  int thread_putnia(struct pdbg_target *target, uint64_t value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->putnia) {
+		PR_ERROR("putnia() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->putnia(thread, value);
 }
 
@@ -292,8 +442,17 @@  int thread_getxer(struct pdbg_target *target, uint64_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->getxer) {
+		PR_ERROR("getxer() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->getxer(thread, value);
 }
 
@@ -302,8 +461,17 @@  int thread_putxer(struct pdbg_target *target, uint64_t value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->putxer) {
+		PR_ERROR("putxer() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->putxer(thread, value);
 }
 
@@ -312,8 +480,17 @@  int thread_getcr(struct pdbg_target *target, uint32_t *value)
 	struct thread *thread;
 
 	assert(pdbg_target_is_class(target, "thread"));
+
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	thread = target_to_thread(target);
 
+	if (!thread->getcr) {
+		PR_ERROR("getcr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->getcr(thread, value);
 }
 
@@ -321,8 +498,17 @@  int thread_putcr(struct pdbg_target *target, uint32_t value)
 {
 	struct thread *thread;
 
+	if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+		return -1;
+
 	assert(pdbg_target_is_class(target, "thread"));
+
 	thread = target_to_thread(target);
 
+	if (!thread->putcr) {
+		PR_ERROR("putcr() not imeplemented for the target\n");
+		return -1;
+	}
+
 	return thread->putcr(thread, value);
 }