Skip to content

Commit c6127e7

Browse files
Automatic merge of 'next' into merge (2025-05-12 10:01)
2 parents ee74be3 + 5a821e2 commit c6127e7

9 files changed

Lines changed: 528 additions & 35 deletions

File tree

Documentation/arch/powerpc/htm.rst

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
.. _htm:
3+
4+
===================================
5+
HTM (Hardware Trace Macro)
6+
===================================
7+
8+
Athira Rajeev, 2 Mar 2025
9+
10+
.. contents::
11+
:depth: 3
12+
13+
14+
Basic overview
15+
==============
16+
17+
H_HTM is used as an interface for executing Hardware Trace Macro (HTM)
18+
functions, including setup, configuration, control and dumping of the HTM data.
19+
For using HTM, it is required to setup HTM buffers and HTM operations can
20+
be controlled using the H_HTM hcall. The hcall can be invoked for any core/chip
21+
of the system from within a partition itself. To use this feature, a debugfs
22+
folder called "htmdump" is present under /sys/kernel/debug/powerpc.
23+
24+
25+
HTM debugfs example usage
26+
=========================
27+
28+
.. code-block:: sh
29+
30+
# ls /sys/kernel/debug/powerpc/htmdump/
31+
coreindexonchip htmcaps htmconfigure htmflags htminfo htmsetup
32+
htmstart htmstatus htmtype nodalchipindex nodeindex trace
33+
34+
Details on each file:
35+
36+
* nodeindex, nodalchipindex, coreindexonchip specifies which partition to configure the HTM for.
37+
* htmtype: specifies the type of HTM. Supported target is hardwareTarget.
38+
* trace: is to read the HTM data.
39+
* htmconfigure: Configure/Deconfigure the HTM. Writing 1 to the file will configure the trace, writing 0 to the file will do deconfigure.
40+
* htmstart: start/Stop the HTM. Writing 1 to the file will start the tracing, writing 0 to the file will stop the tracing.
41+
* htmstatus: get the status of HTM. This is needed to understand the HTM state after each operation.
42+
* htmsetup: set the HTM buffer size. Size of HTM buffer is in power of 2
43+
* htminfo: provides the system processor configuration details. This is needed to understand the appropriate values for nodeindex, nodalchipindex, coreindexonchip.
44+
* htmcaps : provides the HTM capabilities like minimum/maximum buffer size, what kind of tracing the HTM supports etc.
45+
* htmflags : allows to pass flags to hcall. Currently supports controlling the wrapping of HTM buffer.
46+
47+
To see the system processor configuration details:
48+
49+
.. code-block:: sh
50+
51+
# cat /sys/kernel/debug/powerpc/htmdump/htminfo > htminfo_file
52+
53+
The result can be interpreted using hexdump.
54+
55+
To collect HTM traces for a partition represented by nodeindex as
56+
zero, nodalchipindex as 1 and coreindexonchip as 12
57+
58+
.. code-block:: sh
59+
60+
# cd /sys/kernel/debug/powerpc/htmdump/
61+
# echo 2 > htmtype
62+
# echo 33 > htmsetup ( sets 8GB memory for HTM buffer, number is size in power of 2 )
63+
64+
This requires a CEC reboot to get the HTM buffers allocated.
65+
66+
.. code-block:: sh
67+
68+
# cd /sys/kernel/debug/powerpc/htmdump/
69+
# echo 2 > htmtype
70+
# echo 0 > nodeindex
71+
# echo 1 > nodalchipindex
72+
# echo 12 > coreindexonchip
73+
# echo 1 > htmflags # to set noWrap for HTM buffers
74+
# echo 1 > htmconfigure # Configure the HTM
75+
# echo 1 > htmstart # Start the HTM
76+
# echo 0 > htmstart # Stop the HTM
77+
# echo 0 > htmconfigure # Deconfigure the HTM
78+
# cat htmstatus # Dump the status of HTM entries as data
79+
80+
Above will set the htmtype and core details, followed by executing respective HTM operation.
81+
82+
Read the HTM trace data
83+
========================
84+
85+
After starting the trace collection, run the workload
86+
of interest. Stop the trace collection after required period
87+
of time, and read the trace file.
88+
89+
.. code-block:: sh
90+
91+
# cat /sys/kernel/debug/powerpc/htmdump/trace > trace_file
92+
93+
This trace file will contain the relevant instruction traces
94+
collected during the workload execution. And can be used as
95+
input file for trace decoders to understand data.
96+
97+
Benefits of using HTM debugfs interface
98+
=======================================
99+
100+
It is now possible to collect traces for a particular core/chip
101+
from within any partition of the system and decode it. Through
102+
this enablement, a small partition can be dedicated to collect the
103+
trace data and analyze to provide important information for Performance
104+
analysis, Software tuning, or Hardware debug.

arch/powerpc/boot/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ BOOTCPPFLAGS := -nostdinc $(LINUXINCLUDE)
7070
BOOTCPPFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include)
7171

7272
BOOTCFLAGS := $(BOOTTARGETFLAGS) \
73+
-std=gnu11 \
7374
-Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
7475
-fno-strict-aliasing -O2 \
7576
-msoft-float -mno-altivec -mno-vsx \

arch/powerpc/include/asm/plpar_wrappers.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa)
6565
return vpa_call(H_VPA_REG_DTL, cpu, vpa);
6666
}
6767

68+
/*
69+
* Invokes H_HTM hcall with parameters passed from htm_hcall_wrapper.
70+
* flags: Set to hardwareTarget.
71+
* target: Specifies target using node index, nodal chip index and core index.
72+
* operation : action to perform ie configure, start, stop, deconfigure, trace
73+
* based on the HTM type.
74+
* param1, param2, param3: parameters for each action.
75+
*/
6876
static inline long htm_call(unsigned long flags, unsigned long target,
6977
unsigned long operation, unsigned long param1,
7078
unsigned long param2, unsigned long param3)
@@ -73,17 +81,17 @@ static inline long htm_call(unsigned long flags, unsigned long target,
7381
param1, param2, param3);
7482
}
7583

76-
static inline long htm_get_dump_hardware(unsigned long nodeindex,
84+
static inline long htm_hcall_wrapper(unsigned long flags, unsigned long nodeindex,
7785
unsigned long nodalchipindex, unsigned long coreindexonchip,
78-
unsigned long type, unsigned long addr, unsigned long size,
79-
unsigned long offset)
86+
unsigned long type, unsigned long htm_op, unsigned long param1, unsigned long param2,
87+
unsigned long param3)
8088
{
81-
return htm_call(H_HTM_FLAGS_HARDWARE_TARGET,
89+
return htm_call(H_HTM_FLAGS_HARDWARE_TARGET | flags,
8290
H_HTM_TARGET_NODE_INDEX(nodeindex) |
8391
H_HTM_TARGET_NODAL_CHIP_INDEX(nodalchipindex) |
8492
H_HTM_TARGET_CORE_INDEX_ON_CHIP(coreindexonchip),
85-
H_HTM_OP(H_HTM_OP_DUMP_DATA) | H_HTM_TYPE(type),
86-
addr, size, offset);
93+
H_HTM_OP(htm_op) | H_HTM_TYPE(type),
94+
param1, param2, param3);
8795
}
8896

8997
extern void vpa_init(int cpu);

arch/powerpc/platforms/44x/gpio.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ __ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
7575
clrbits32(&regs->or, GPIO_MASK(gpio));
7676
}
7777

78-
static void
79-
ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
78+
static int ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
8079
{
8180
struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
8281
unsigned long flags;
@@ -88,6 +87,8 @@ ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
8887
spin_unlock_irqrestore(&chip->lock, flags);
8988

9089
pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
90+
91+
return 0;
9192
}
9293

9394
static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
@@ -179,7 +180,7 @@ static int __init ppc4xx_add_gpiochips(void)
179180
gc->direction_input = ppc4xx_gpio_dir_in;
180181
gc->direction_output = ppc4xx_gpio_dir_out;
181182
gc->get = ppc4xx_gpio_get;
182-
gc->set = ppc4xx_gpio_set;
183+
gc->set_rv = ppc4xx_gpio_set;
183184

184185
ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc);
185186
if (ret)

arch/powerpc/platforms/52xx/mpc52xx_gpt.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
280280
return (in_be32(&gpt->regs->status) >> 8) & 1;
281281
}
282282

283-
static void
283+
static int
284284
mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v)
285285
{
286286
struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc);
@@ -293,6 +293,8 @@ mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v)
293293
raw_spin_lock_irqsave(&gpt->lock, flags);
294294
clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK, r);
295295
raw_spin_unlock_irqrestore(&gpt->lock, flags);
296+
297+
return 0;
296298
}
297299

298300
static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
@@ -334,7 +336,7 @@ static void mpc52xx_gpt_gpio_setup(struct mpc52xx_gpt_priv *gpt)
334336
gpt->gc.direction_input = mpc52xx_gpt_gpio_dir_in;
335337
gpt->gc.direction_output = mpc52xx_gpt_gpio_dir_out;
336338
gpt->gc.get = mpc52xx_gpt_gpio_get;
337-
gpt->gc.set = mpc52xx_gpt_gpio_set;
339+
gpt->gc.set_rv = mpc52xx_gpt_gpio_set;
338340
gpt->gc.base = -1;
339341
gpt->gc.parent = gpt->dev;
340342

arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,25 +92,28 @@ static void mcu_power_off(void)
9292
mutex_unlock(&mcu->lock);
9393
}
9494

95-
static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
95+
static int mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
9696
{
9797
struct mcu *mcu = gpiochip_get_data(gc);
9898
u8 bit = 1 << (4 + gpio);
99+
int ret;
99100

100101
mutex_lock(&mcu->lock);
101102
if (val)
102103
mcu->reg_ctrl &= ~bit;
103104
else
104105
mcu->reg_ctrl |= bit;
105106

106-
i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
107+
ret = i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
108+
mcu->reg_ctrl);
107109
mutex_unlock(&mcu->lock);
110+
111+
return ret;
108112
}
109113

110114
static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
111115
{
112-
mcu_gpio_set(gc, gpio, val);
113-
return 0;
116+
return mcu_gpio_set(gc, gpio, val);
114117
}
115118

116119
static int mcu_gpiochip_add(struct mcu *mcu)
@@ -123,7 +126,7 @@ static int mcu_gpiochip_add(struct mcu *mcu)
123126
gc->can_sleep = 1;
124127
gc->ngpio = MCU_NUM_GPIO;
125128
gc->base = -1;
126-
gc->set = mcu_gpio_set;
129+
gc->set_rv = mcu_gpio_set;
127130
gc->direction_output = mcu_gpio_dir_out;
128131
gc->parent = dev;
129132

arch/powerpc/platforms/8xx/cpm1.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ static void __cpm1_gpio16_set(struct cpm1_gpio16_chip *cpm1_gc, u16 pin_mask, in
417417
out_be16(&iop->dat, cpm1_gc->cpdata);
418418
}
419419

420-
static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
420+
static int cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
421421
{
422422
struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(gc);
423423
unsigned long flags;
@@ -428,6 +428,8 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
428428
__cpm1_gpio16_set(cpm1_gc, pin_mask, value);
429429

430430
spin_unlock_irqrestore(&cpm1_gc->lock, flags);
431+
432+
return 0;
431433
}
432434

433435
static int cpm1_gpio16_to_irq(struct gpio_chip *gc, unsigned int gpio)
@@ -497,7 +499,7 @@ int cpm1_gpiochip_add16(struct device *dev)
497499
gc->direction_input = cpm1_gpio16_dir_in;
498500
gc->direction_output = cpm1_gpio16_dir_out;
499501
gc->get = cpm1_gpio16_get;
500-
gc->set = cpm1_gpio16_set;
502+
gc->set_rv = cpm1_gpio16_set;
501503
gc->to_irq = cpm1_gpio16_to_irq;
502504
gc->parent = dev;
503505
gc->owner = THIS_MODULE;
@@ -554,7 +556,7 @@ static void __cpm1_gpio32_set(struct cpm1_gpio32_chip *cpm1_gc, u32 pin_mask, in
554556
out_be32(&iop->dat, cpm1_gc->cpdata);
555557
}
556558

557-
static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
559+
static int cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
558560
{
559561
struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(gc);
560562
unsigned long flags;
@@ -565,6 +567,8 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
565567
__cpm1_gpio32_set(cpm1_gc, pin_mask, value);
566568

567569
spin_unlock_irqrestore(&cpm1_gc->lock, flags);
570+
571+
return 0;
568572
}
569573

570574
static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
@@ -618,7 +622,7 @@ int cpm1_gpiochip_add32(struct device *dev)
618622
gc->direction_input = cpm1_gpio32_dir_in;
619623
gc->direction_output = cpm1_gpio32_dir_out;
620624
gc->get = cpm1_gpio32_get;
621-
gc->set = cpm1_gpio32_set;
625+
gc->set_rv = cpm1_gpio32_set;
622626
gc->parent = dev;
623627
gc->owner = THIS_MODULE;
624628

0 commit comments

Comments
 (0)