#include <config.h>
#include <object/structures.h>
#include <object/tcb.h>
#include <model/statedata.h>
#include <machine/capdl.h>
#include <arch/machine/capdl.h>
#include <machine/io.h>
#include <plat/machine/hardware.h>
#ifdef CONFIG_DEBUG_BUILD
#define ARCH 0xe0
#define PD_READ_SIZE BIT(PD_INDEX_BITS)
#define PT_READ_SIZE BIT(PT_INDEX_BITS)
#define ASID_POOL_READ_SIZE BIT(ASID_POOL_INDEX_BITS)
static int getDecodedChar(unsigned char *result)
{
unsigned char c;
c = getDebugChar();
if (c == START) {
return 1;
}
if (c == ESCAPE) {
c = getDebugChar();
if (c == START) {
return 1;
}
switch (c) {
case ESCAPE_ESCAPE:
*result = ESCAPE;
break;
case START_ESCAPE:
*result = START;
break;
case END_ESCAPE:
*result = END;
break;
default:
if (c >= 20 && c < 40) {
*result = c - 20;
}
}
return 0;
} else {
*result = c;
return 0;
}
}
static void putEncodedChar(unsigned char c)
{
switch (c) {
case ESCAPE:
putDebugChar(ESCAPE);
putDebugChar(ESCAPE_ESCAPE);
break;
case START:
putDebugChar(ESCAPE);
putDebugChar(START_ESCAPE);
break;
case END:
putDebugChar(ESCAPE);
putDebugChar(END_ESCAPE);
break;
default:
if (c < 20) {
putDebugChar(ESCAPE);
putDebugChar(c + 20);
} else {
putDebugChar(c);
}
}
}
static int getArg32(unsigned int *res)
{
unsigned char b1 = 0;
unsigned char b2 = 0;
unsigned char b3 = 0;
unsigned char b4 = 0;
if (getDecodedChar(&b1)) {
return 1;
}
if (getDecodedChar(&b2)) {
return 1;
}
if (getDecodedChar(&b3)) {
return 1;
}
if (getDecodedChar(&b4)) {
return 1;
}
*res = (b1 << 24 ) | (b2 << 16) | (b3 << 8) | b4;
return 0;
}
static void sendWord(unsigned int word)
{
putEncodedChar(word & 0xff);
putEncodedChar((word >> 8) & 0xff);
putEncodedChar((word >> 16) & 0xff);
putEncodedChar((word >> 24) & 0xff);
}
static cte_t *getMDBParent(cte_t *slot)
{
cte_t *oldSlot = CTE_PTR(mdb_node_get_mdbPrev(slot->cteMDBNode));
while (oldSlot != 0 && !isMDBParentOf(oldSlot, slot)) {
oldSlot = CTE_PTR(mdb_node_get_mdbPrev(oldSlot->cteMDBNode));
}
return oldSlot;
}
static void sendPD(unsigned int address)
{
word_t i, exists;
pde_t *start = (pde_t *)address;
for (i = 0; i < PD_READ_SIZE; i++) {
pde_t pde = start[i];
exists = 0;
if (pde_get_pdeType(pde) == pde_pde_coarse && pde_pde_coarse_get_address(pde) != 0) {
exists = 1;
} else if (pde_get_pdeType(pde) == pde_pde_section && (pde_pde_section_get_address(pde) != 0 ||
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
pde_pde_section_get_HAP(pde))) {
#else
pde_pde_section_get_AP(pde))) {
#endif
exists = 1;
}
if (exists != 0 && i < kernelBase >> pageBitsForSize(ARMSection)) {
sendWord(i);
sendWord(pde.words[0]);
}
}
}
static void sendPT(unsigned int address)
{
word_t i, exists;
pte_t *start = (pte_t *)address;
for (i = 0; i < PT_READ_SIZE; i++) {
pte_t pte = start[i];
exists = 0;
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
if (pte_get_pteType(pte) == pte_pte_small && (pte_pte_small_get_address(pte) != 0 ||
pte_pte_small_get_HAP(pte))) {
exists = 1;
}
#else
if (pte_get_pteType(pte) == pte_pte_large && (pte_pte_large_get_address(pte) != 0 ||
pte_pte_large_get_AP(pte))) {
exists = 1;
} else if (pte_get_pteType(pte) == pte_pte_small && (pte_pte_small_get_address(pte) != 0 ||
pte_pte_small_get_AP(pte))) {
exists = 1;
}
#endif
if (exists != 0) {
sendWord(i);
sendWord(pte.words[0]);
}
}
}
static void sendASIDPool(unsigned int address)
{
word_t i;
pde_t **start = (pde_t **)address;
for (i = 0; i < ASID_POOL_READ_SIZE; i++) {
pde_t *pde = start[i];
if (pde != 0) {
sendWord(i);
sendWord((unsigned int)pde);
}
}
}
static void sendRunqueues(void)
{
word_t i;
sendWord((unsigned int) NODE_STATE(ksCurThread));
for (i = 0; i < NUM_READY_QUEUES; i++) {
tcb_t *current = NODE_STATE(ksReadyQueues[i]).head;
if (current != 0) {
while (current != NODE_STATE(ksReadyQueues[i]).end) {
sendWord((unsigned int)current);
current = current -> tcbSchedNext;
}
sendWord((unsigned int)current);
}
}
}
static void sendEPQueue(unsigned int epptr)
{
tcb_t *current = (tcb_t *)endpoint_ptr_get_epQueue_head((endpoint_t *)epptr);
tcb_t *tail = (tcb_t *)endpoint_ptr_get_epQueue_tail((endpoint_t *)epptr);
if (current == 0) {
return;
}
while (current != tail) {
sendWord((unsigned int)current);
current = current->tcbEPNext;
}
sendWord((unsigned int)current);
}
static void sendCNode(unsigned int address, unsigned int sizebits)
{
word_t i;
cte_t *start = (cte_t *)address;
for (i = 0; i < (1 << sizebits); i++) {
cap_t cap = start[i].cap;
if (cap_get_capType(cap) != cap_null_cap) {
cte_t *parent = getMDBParent(&start[i]);
sendWord(i);
sendWord(cap.words[0]);
sendWord(cap.words[1]);
sendWord((unsigned int)parent);
}
}
}
static void sendIRQNode(void)
{
sendCNode((unsigned int)intStateIRQNode, 8);
}
static void sendVersion(void)
{
sendWord(ARCH);
sendWord(CAPDL_VERSION);
}
void capDL(void)
{
int result;
int done = 0;
while (done == 0) {
unsigned char c;
do {
c = getDebugChar();
} while (c != START);
do {
result = getDecodedChar(&c);
if (result) {
continue;
}
switch (c) {
case PD_COMMAND: {
unsigned int arg;
result = getArg32(&arg);
if (result) {
continue;
}
sendPD(arg);
putDebugChar(END);
}
break;
case PT_COMMAND: {
unsigned int arg;
result = getArg32(&arg);
if (result) {
continue;
}
sendPT(arg);
putDebugChar(END);
}
break;
case ASID_POOL_COMMAND: {
unsigned int arg;
result = getArg32(&arg);
if (result) {
continue;
}
sendASIDPool(arg);
putDebugChar(END);
}
break;
case RQ_COMMAND: {
sendRunqueues();
putDebugChar(END);
result = 0;
}
break;
case EP_COMMAND: {
unsigned int arg;
result = getArg32(&arg);
if (result) {
continue;
}
sendEPQueue(arg);
putDebugChar(END);
}
break;
case CN_COMMAND: {
unsigned int address, sizebits;
result = getArg32(&address);
if (result) {
continue;
}
result = getArg32(&sizebits);
if (result) {
continue;
}
sendCNode(address, sizebits);
putDebugChar(END);
}
break;
case IRQ_COMMAND: {
sendIRQNode();
putDebugChar(END);
result = 0;
}
break;
case VERSION_COMMAND: {
sendVersion();
putDebugChar(END);
}
break;
case DONE: {
done = 1;
putDebugChar(END);
}
default:
result = 0;
break;
}
} while (result);
}
}
#endif