Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/coresight/coresight_cmd.c
/*- | /*- | ||||
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com> | * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com> | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* This software was developed by SRI International and the University of | * This software was developed by SRI International and the University of | ||||
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 | * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 | ||||
* ("CTSRD"), as part of the DARPA CRASH research programme. | * ("CTSRD"), as part of the DARPA CRASH research programme. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
Show All 28 Lines | |||||
#include <arm64/coresight/coresight.h> | #include <arm64/coresight/coresight.h> | ||||
#include "coresight_if.h" | #include "coresight_if.h" | ||||
extern struct coresight_device_list cs_devs; | extern struct coresight_device_list cs_devs; | ||||
static struct coresight_device * | static struct coresight_device * | ||||
coresight_next_device(struct coresight_device *cs_dev, | coresight_next_device(struct coresight_device *cs_dev, | ||||
struct coresight_event *event) | struct coresight_pipeline *pipeline) | ||||
{ | { | ||||
struct coresight_device *out; | struct coresight_device *out; | ||||
struct endpoint *out_endp; | struct endpoint *out_endp, *src_endp; | ||||
struct endpoint *endp; | struct endpoint *endp; | ||||
TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) { | TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) { | ||||
if (endp->input != 0) | if (endp->input != 0) | ||||
continue; | continue; | ||||
out = coresight_get_output_device(endp, &out_endp); | out = coresight_get_output_device(cs_dev, endp, &out_endp); | ||||
if (out != NULL) { | if (out != NULL) { | ||||
if (LIST_EMPTY(&event->endplist)) { | if (TAILQ_EMPTY(&pipeline->endplist)) { | ||||
/* Add source device */ | /* Add source device */ | ||||
endp->cs_dev = cs_dev; | src_endp = malloc(sizeof(struct endpoint), | ||||
LIST_INSERT_HEAD(&event->endplist, endp, | M_CORESIGHT, M_WAITOK | M_ZERO); | ||||
memcpy(src_endp, endp, sizeof(struct endpoint)); | |||||
src_endp->cs_dev = cs_dev; | |||||
TAILQ_INSERT_TAIL(&pipeline->endplist, src_endp, | |||||
endplink); | endplink); | ||||
} | } | ||||
/* Add output device */ | /* Add output device */ | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("Adding device %s to the chain\n", | printf("Adding device %s to the chain\n", | ||||
device_get_nameunit(out->dev)); | device_get_nameunit(out->dev)); | ||||
out_endp->cs_dev = out; | out_endp->cs_dev = out; | ||||
LIST_INSERT_HEAD(&event->endplist, out_endp, endplink); | TAILQ_INSERT_TAIL(&pipeline->endplist, out_endp, | ||||
endplink); | |||||
return (out); | return (out); | ||||
} | } | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
static int | static int | ||||
coresight_build_list(struct coresight_device *cs_dev, | coresight_build_pipeline(struct coresight_device *cs_dev, | ||||
struct coresight_event *event) | struct coresight_pipeline *pipeline) | ||||
{ | { | ||||
struct coresight_device *out; | struct coresight_device *out; | ||||
out = cs_dev; | out = cs_dev; | ||||
while (out != NULL) | while (out != NULL) | ||||
out = coresight_next_device(out, event); | out = coresight_next_device(out, pipeline); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
coresight_init_event(int cpu, struct coresight_event *event) | coresight_init_pipeline(struct coresight_pipeline *pipeline, int cpu) | ||||
{ | { | ||||
struct coresight_device *cs_dev; | struct coresight_device *cs_dev; | ||||
struct endpoint *endp; | struct endpoint *endp; | ||||
int error; | |||||
/* Start building path from source device */ | /* Start building path from source device */ | ||||
TAILQ_FOREACH(cs_dev, &cs_devs, link) { | TAILQ_FOREACH(cs_dev, &cs_devs, link) { | ||||
if (cs_dev->dev_type == event->src && | if (cs_dev->dev_type == pipeline->src && | ||||
cs_dev->pdata->cpu == cpu) { | cs_dev->pdata->cpu == cpu) { | ||||
LIST_INIT(&event->endplist); | TAILQ_INIT(&pipeline->endplist); | ||||
coresight_build_list(cs_dev, event); | coresight_build_pipeline(cs_dev, pipeline); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* Ensure Coresight is initialized for the CPU */ | /* Ensure Coresight is initialized for the CPU */ | ||||
TAILQ_FOREACH(cs_dev, &cs_devs, link) { | TAILQ_FOREACH(cs_dev, &cs_devs, link) { | ||||
if (cs_dev->dev_type == CORESIGHT_CPU_DEBUG && | if (cs_dev->dev_type == CORESIGHT_CPU_DEBUG && | ||||
cs_dev->pdata->cpu == cpu) | cs_dev->pdata->cpu == cpu) { | ||||
CORESIGHT_INIT(cs_dev->dev); | error = CORESIGHT_INIT(cs_dev->dev); | ||||
if (error != ENXIO && error != 0) | |||||
return (error); | |||||
} | } | ||||
} | |||||
/* Init all devices in the path */ | /* Init all devices in the path */ | ||||
LIST_FOREACH(endp, &event->endplist, endplink) { | TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | ||||
cs_dev = endp->cs_dev; | cs_dev = endp->cs_dev; | ||||
CORESIGHT_INIT(cs_dev->dev); | error = CORESIGHT_INIT(cs_dev->dev); | ||||
if (error != ENXIO && error != 0) | |||||
return (error); | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
coresight_enable(int cpu, struct coresight_event *event) | coresight_deinit_pipeline(struct coresight_pipeline *pipeline) | ||||
{ | { | ||||
struct coresight_device *cs_dev; | struct coresight_device *cs_dev; | ||||
struct endpoint *endp, *tmp; | |||||
TAILQ_FOREACH_SAFE(endp, &pipeline->endplist, endplink, tmp) { | |||||
cs_dev = endp->cs_dev; | |||||
CORESIGHT_DEINIT(cs_dev->dev); | |||||
TAILQ_REMOVE(&pipeline->endplist, endp, endplink); | |||||
free(endp, M_CORESIGHT); | |||||
} | |||||
} | |||||
int | |||||
coresight_setup(struct coresight_pipeline *pipeline) | |||||
{ | |||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | struct endpoint *endp; | ||||
int error; | |||||
LIST_FOREACH(endp, &event->endplist, endplink) { | TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | ||||
cs_dev = endp->cs_dev; | cs_dev = endp->cs_dev; | ||||
CORESIGHT_ENABLE(cs_dev->dev, endp, event); | error = CORESIGHT_SETUP(cs_dev->dev, endp, pipeline); | ||||
if (error != ENXIO && error != 0) | |||||
return (error); | |||||
} | } | ||||
return (0); | |||||
} | } | ||||
int | |||||
coresight_configure(struct coresight_pipeline *pipeline, | |||||
struct hwt_context *ctx) | |||||
{ | |||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | |||||
int error; | |||||
TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | |||||
cs_dev = endp->cs_dev; | |||||
error = CORESIGHT_CONFIGURE(cs_dev->dev, endp, pipeline, ctx); | |||||
if (error != ENXIO && error != 0) | |||||
return (error); | |||||
} | |||||
return (0); | |||||
} | |||||
int | |||||
coresight_start(struct coresight_pipeline *pipeline) | |||||
{ | |||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | |||||
int error; | |||||
TAILQ_FOREACH_REVERSE(endp, &pipeline->endplist, endplistname, | |||||
endplink) { | |||||
cs_dev = endp->cs_dev; | |||||
error = CORESIGHT_START(cs_dev->dev, endp, pipeline); | |||||
if (error != ENXIO && error != 0) | |||||
return (error); | |||||
} | |||||
return (0); | |||||
} | |||||
void | void | ||||
coresight_disable(int cpu, struct coresight_event *event) | coresight_stop(struct coresight_pipeline *pipeline) | ||||
{ | { | ||||
struct coresight_device *cs_dev; | struct coresight_device *cs_dev; | ||||
struct endpoint *endp; | struct endpoint *endp; | ||||
LIST_FOREACH(endp, &event->endplist, endplink) { | TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | ||||
cs_dev = endp->cs_dev; | cs_dev = endp->cs_dev; | ||||
CORESIGHT_DISABLE(cs_dev->dev, endp, event); | CORESIGHT_STOP(cs_dev->dev, endp, pipeline); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
coresight_read(int cpu, struct coresight_event *event) | coresight_enable(struct coresight_pipeline *pipeline) | ||||
{ | { | ||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | struct endpoint *endp; | ||||
LIST_FOREACH(endp, &event->endplist, endplink) | TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | ||||
CORESIGHT_READ(endp->cs_dev->dev, endp, event); | cs_dev = endp->cs_dev; | ||||
CORESIGHT_ENABLE(cs_dev->dev, endp, pipeline); | |||||
} | |||||
} | |||||
void | |||||
coresight_disable(struct coresight_pipeline *pipeline) | |||||
{ | |||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | |||||
TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | |||||
cs_dev = endp->cs_dev; | |||||
CORESIGHT_DISABLE(cs_dev->dev, endp, pipeline); | |||||
} | |||||
} | |||||
void | |||||
coresight_dump(struct coresight_pipeline *pipeline) | |||||
{ | |||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | |||||
TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | |||||
cs_dev = endp->cs_dev; | |||||
CORESIGHT_DUMP(cs_dev->dev); | |||||
} | |||||
} | |||||
int | |||||
coresight_read(struct coresight_pipeline *pipeline) | |||||
{ | |||||
struct coresight_device *cs_dev; | |||||
struct endpoint *endp; | |||||
int error; | |||||
TAILQ_FOREACH(endp, &pipeline->endplist, endplink) { | |||||
cs_dev = endp->cs_dev; | |||||
error = CORESIGHT_READ(cs_dev->dev, endp, pipeline); | |||||
if (error != ENXIO && error != 0) | |||||
return (error); | |||||
} | |||||
return (0); | |||||
} | } |