diff --git a/Documentation/arch/powerpc/index.rst b/Documentation/arch/powerpc/index.rst index a50834798454..9749f6dc258f 100644 --- a/Documentation/arch/powerpc/index.rst +++ b/Documentation/arch/powerpc/index.rst @@ -26,6 +26,7 @@ powerpc isa-versions kaslr-booke32 mpc52xx + kvm-nested papr_hcalls pci_iov_resource_on_powernv pmu-ebb diff --git a/Documentation/arch/powerpc/kvm-nested.rst b/Documentation/arch/powerpc/kvm-nested.rst new file mode 100644 index 000000000000..630602a8aa00 --- /dev/null +++ b/Documentation/arch/powerpc/kvm-nested.rst @@ -0,0 +1,634 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================================== +Nested KVM on POWER +==================================== + +Introduction +============ + +This document explains how a guest operating system can act as a +hypervisor and run nested guests through the use of hypercalls, if the +hypervisor has implemented them. The terms L0, L1, and L2 are used to +refer to different software entities. L0 is the hypervisor mode entity +that would normally be called the "host" or "hypervisor". L1 is a +guest virtual machine that is directly run under L0 and is initiated +and controlled by L0. L2 is a guest virtual machine that is initiated +and controlled by L1 acting as a hypervisor. + +Existing API +============ + +Linux/KVM has had support for Nesting as an L0 or L1 since 2018 + +The L0 code was added:: + + commit 8e3f5fc1045dc49fd175b978c5457f5f51e7a2ce + Author: Paul Mackerras + Date: Mon Oct 8 16:31:03 2018 +1100 + KVM: PPC: Book3S HV: Framework and hcall stubs for nested virtualization + +The L1 code was added:: + + commit 360cae313702cdd0b90f82c261a8302fecef030a + Author: Paul Mackerras + Date: Mon Oct 8 16:31:04 2018 +1100 + KVM: PPC: Book3S HV: Nested guest entry via hypercall + +This API works primarily using a single hcall h_enter_nested(). This +call made by the L1 to tell the L0 to start an L2 vCPU with the given +state. The L0 then starts this L2 and runs until an L2 exit condition +is reached. Once the L2 exits, the state of the L2 is given back to +the L1 by the L0. The full L2 vCPU state is always transferred from +and to L1 when the L2 is run. The L0 doesn't keep any state on the L2 +vCPU (except in the short sequence in the L0 on L1 -> L2 entry and L2 +-> L1 exit). + +The only state kept by the L0 is the partition table. The L1 registers +it's partition table using the h_set_partition_table() hcall. All +other state held by the L0 about the L2s is cached state (such as +shadow page tables). + +The L1 may run any L2 or vCPU without first informing the L0. It +simply starts the vCPU using h_enter_nested(). The creation of L2s and +vCPUs is done implicitly whenever h_enter_nested() is called. + +In this document, we call this existing API the v1 API. + +New PAPR API +=============== + +The new PAPR API changes from the v1 API such that the creating L2 and +associated vCPUs is explicit. In this document, we call this the v2 +API. + +h_enter_nested() is replaced with H_GUEST_VCPU_RUN(). Before this can +be called the L1 must explicitly create the L2 using h_guest_create() +and any associated vCPUs() created with h_guest_create_vCPU(). Getting +and setting vCPU state can also be performed using h_guest_{g|s}et +hcall. + +The basic execution flow is for an L1 to create an L2, run it, and +delete it is: + +- L1 and L0 negotiate capabilities with H_GUEST_{G,S}ET_CAPABILITIES() + (normally at L1 boot time). + +- L1 requests the L0 create an L2 with H_GUEST_CREATE() and receives a token + +- L1 requests the L0 create an L2 vCPU with H_GUEST_CREATE_VCPU() + +- L1 and L0 communicate the vCPU state using the H_GUEST_{G,S}ET() hcall + +- L1 requests the L0 runs the vCPU running H_GUEST_VCPU_RUN() hcall + +- L1 deletes L2 with H_GUEST_DELETE() + +More details of the individual hcalls follows: + +HCALL Details +============= + +This documentation is provided to give an overall understating of the +API. It doesn't aim to provide all the details required to implement +an L1 or L0. Latest version of PAPR can be referred to for more details. + +All these HCALLs are made by the L1 to the L0. + +H_GUEST_GET_CAPABILITIES() +-------------------------- + +This is called to get the capabilities of the L0 nested +hypervisor. This includes capabilities such the CPU versions (eg +POWER9, POWER10) that are supported as L2s:: + + H_GUEST_GET_CAPABILITIES(uint64 flags) + + Parameters: + Input: + flags: Reserved + Output: + R3: Return code + R4: Hypervisor Supported Capabilities bitmap 1 + +H_GUEST_SET_CAPABILITIES() +-------------------------- + +This is called to inform the L0 of the capabilities of the L1 +hypervisor. The set of flags passed here are the same as +H_GUEST_GET_CAPABILITIES() + +Typically, GET will be called first and then SET will be called with a +subset of the flags returned from GET. This process allows the L0 and +L1 to negotiate an agreed set of capabilities:: + + H_GUEST_SET_CAPABILITIES(uint64 flags, + uint64 capabilitiesBitmap1) + Parameters: + Input: + flags: Reserved + capabilitiesBitmap1: Only capabilities advertised through + H_GUEST_GET_CAPABILITIES + Output: + R3: Return code + R4: If R3 = H_P2: The number of invalid bitmaps + R5: If R3 = H_P2: The index of first invalid bitmap + +H_GUEST_CREATE() +---------------- + +This is called to create an L2. A unique ID of the L2 created +(similar to an LPID) is returned, which can be used on subsequent HCALLs to +identify the L2:: + + H_GUEST_CREATE(uint64 flags, + uint64 continueToken); + Parameters: + Input: + flags: Reserved + continueToken: Initial call set to -1. Subsequent calls, + after H_Busy or H_LongBusyOrder has been + returned, value that was returned in R4. + Output: + R3: Return code. Notable: + H_Not_Enough_Resources: Unable to create Guest VCPU due to not + enough Hypervisor memory. See H_GUEST_CREATE_GET_STATE(flags = + takeOwnershipOfVcpuState) + R4: If R3 = H_Busy or_H_LongBusyOrder -> continueToken + +H_GUEST_CREATE_VCPU() +--------------------- + +This is called to create a vCPU associated with an L2. The L2 id +(returned from H_GUEST_CREATE()) should be passed it. Also passed in +is a unique (for this L2) vCPUid. This vCPUid is allocated by the +L1:: + + H_GUEST_CREATE_VCPU(uint64 flags, + uint64 guestId, + uint64 vcpuId); + Parameters: + Input: + flags: Reserved + guestId: ID obtained from H_GUEST_CREATE + vcpuId: ID of the vCPU to be created. This must be within the + range of 0 to 2047 + Output: + R3: Return code. Notable: + H_Not_Enough_Resources: Unable to create Guest VCPU due to not + enough Hypervisor memory. See H_GUEST_CREATE_GET_STATE(flags = + takeOwnershipOfVcpuState) + +H_GUEST_GET_STATE() +------------------- + +This is called to get state associated with an L2 (Guest-wide or vCPU specific). +This info is passed via the Guest State Buffer (GSB), a standard format as +explained later in this doc, necessary details below: + +This can get either L2 wide or vcpu specific information. Examples of +L2 wide is the timebase offset or process scoped page table +info. Examples of vCPU specific are GPRs or VSRs. A bit in the flags +parameter specifies if this call is L2 wide or vCPU specific and the +IDs in the GSB must match this. + +The L1 provides a pointer to the GSB as a parameter to this call. Also +provided is the L2 and vCPU IDs associated with the state to set. + +The L1 writes only the IDs and sizes in the GSB. L0 writes the +associated values for each ID in the GSB:: + + H_GUEST_GET_STATE(uint64 flags, + uint64 guestId, + uint64 vcpuId, + uint64 dataBuffer, + uint64 dataBufferSizeInBytes); + Parameters: + Input: + flags: + Bit 0: getGuestWideState: Request state of the Guest instead + of an individual VCPU. + Bit 1: takeOwnershipOfVcpuState Indicate the L1 is taking + over ownership of the VCPU state and that the L0 can free + the storage holding the state. The VCPU state will need to + be returned to the Hypervisor via H_GUEST_SET_STATE prior + to H_GUEST_RUN_VCPU being called for this VCPU. The data + returned in the dataBuffer is in a Hypervisor internal + format. + Bits 2-63: Reserved + guestId: ID obtained from H_GUEST_CREATE + vcpuId: ID of the vCPU pass to H_GUEST_CREATE_VCPU + dataBuffer: A L1 real address of the GSB. + If takeOwnershipOfVcpuState, size must be at least the size + returned by ID=0x0001 + dataBufferSizeInBytes: Size of dataBuffer + Output: + R3: Return code + R4: If R3 = H_Invalid_Element_Id: The array index of the bad + element ID. + If R3 = H_Invalid_Element_Size: The array index of the bad + element size. + If R3 = H_Invalid_Element_Value: The array index of the bad + element value. + +H_GUEST_SET_STATE() +------------------- + +This is called to set L2 wide or vCPU specific L2 state. This info is +passed via the Guest State Buffer (GSB), necessary details below: + +This can set either L2 wide or vcpu specific information. Examples of +L2 wide is the timebase offset or process scoped page table +info. Examples of vCPU specific are GPRs or VSRs. A bit in the flags +parameter specifies if this call is L2 wide or vCPU specific and the +IDs in the GSB must match this. + +The L1 provides a pointer to the GSB as a parameter to this call. Also +provided is the L2 and vCPU IDs associated with the state to set. + +The L1 writes all values in the GSB and the L0 only reads the GSB for +this call:: + + H_GUEST_SET_STATE(uint64 flags, + uint64 guestId, + uint64 vcpuId, + uint64 dataBuffer, + uint64 dataBufferSizeInBytes); + Parameters: + Input: + flags: + Bit 0: getGuestWideState: Request state of the Guest instead + of an individual VCPU. + Bit 1: returnOwnershipOfVcpuState Return Guest VCPU state. See + GET_STATE takeOwnershipOfVcpuState + Bits 2-63: Reserved + guestId: ID obtained from H_GUEST_CREATE + vcpuId: ID of the vCPU pass to H_GUEST_CREATE_VCPU + dataBuffer: A L1 real address of the GSB. + If takeOwnershipOfVcpuState, size must be at least the size + returned by ID=0x0001 + dataBufferSizeInBytes: Size of dataBuffer + Output: + R3: Return code + R4: If R3 = H_Invalid_Element_Id: The array index of the bad + element ID. + If R3 = H_Invalid_Element_Size: The array index of the bad + element size. + If R3 = H_Invalid_Element_Value: The array index of the bad + element value. + +H_GUEST_RUN_VCPU() +------------------ + +This is called to run an L2 vCPU. The L2 and vCPU IDs are passed in as +parameters. The vCPU runs with the state set previously using +H_GUEST_SET_STATE(). When the L2 exits, the L1 will resume from this +hcall. + +This hcall also has associated input and output GSBs. Unlike +H_GUEST_{S,G}ET_STATE(), these GSB pointers are not passed in as +parameters to the hcall (This was done in the interest of +performance). The locations of these GSBs must be preregistered using +the H_GUEST_SET_STATE() call with ID 0x0c00 and 0x0c01 (see table +below). + +The input GSB may contain only VCPU specific elements to be set. This +GSB may also contain zero elements (ie 0 in the first 4 bytes of the +GSB) if nothing needs to be set. + +On exit from the hcall, the output buffer is filled with elements +determined by the L0. The reason for the exit is contained in GPR4 (ie +NIP is put in GPR4). The elements returned depend on the exit +type. For example, if the exit reason is the L2 doing a hcall (GPR4 = +0xc00), then GPR3-12 are provided in the output GSB as this is the +state likely needed to service the hcall. If additional state is +needed, H_GUEST_GET_STATE() may be called by the L1. + +To synthesize interrupts in the L2, when calling H_GUEST_RUN_VCPU() +the L1 may set a flag (as a hcall parameter) and the L0 will +synthesize the interrupt in the L2. Alternatively, the L1 may +synthesize the interrupt itself using H_GUEST_SET_STATE() or the +H_GUEST_RUN_VCPU() input GSB to set the state appropriately:: + + H_GUEST_RUN_VCPU(uint64 flags, + uint64 guestId, + uint64 vcpuId, + uint64 dataBuffer, + uint64 dataBufferSizeInBytes); + Parameters: + Input: + flags: + Bit 0: generateExternalInterrupt: Generate an external interrupt + Bit 1: generatePrivilegedDoorbell: Generate a Privileged Doorbell + Bit 2: sendToSystemReset”: Generate a System Reset Interrupt + Bits 3-63: Reserved + guestId: ID obtained from H_GUEST_CREATE + vcpuId: ID of the vCPU pass to H_GUEST_CREATE_VCPU + Output: + R3: Return code + R4: If R3 = H_Success: The reason L1 VCPU exited (ie. NIA) + 0x000: The VCPU stopped running for an unspecified reason. An + example of this is the Hypervisor stopping a VCPU running + due to an outstanding interrupt for the Host Partition. + 0x980: HDEC + 0xC00: HCALL + 0xE00: HDSI + 0xE20: HISI + 0xE40: HEA + 0xF80: HV Fac Unavail + If R3 = H_Invalid_Element_Id, H_Invalid_Element_Size, or + H_Invalid_Element_Value: R4 is offset of the invalid element + in the input buffer. + +H_GUEST_DELETE() +---------------- + +This is called to delete an L2. All associated vCPUs are also +deleted. No specific vCPU delete call is provided. + +A flag may be provided to delete all guests. This is used to reset the +L0 in the case of kdump/kexec:: + + H_GUEST_DELETE(uint64 flags, + uint64 guestId) + Parameters: + Input: + flags: + Bit 0: deleteAllGuests: deletes all guests + Bits 1-63: Reserved + guestId: ID obtained from H_GUEST_CREATE + Output: + R3: Return code + +Guest State Buffer +================== + +The Guest State Buffer (GSB) is the main method of communicating state +about the L2 between the L1 and L0 via H_GUEST_{G,S}ET() and +H_GUEST_VCPU_RUN() calls. + +State may be associated with a whole L2 (eg timebase offset) or a +specific L2 vCPU (eg. GPR state). Only L2 VCPU state maybe be set by +H_GUEST_VCPU_RUN(). + +All data in the GSB is big endian (as is standard in PAPR) + +The Guest state buffer has a header which gives the number of +elements, followed by the GSB elements themselves. + +GSB header: + ++----------+----------+-------------------------------------------+ +| Offset | Size | Purpose | +| Bytes | Bytes | | ++==========+==========+===========================================+ +| 0 | 4 | Number of elements | ++----------+----------+-------------------------------------------+ +| 4 | | Guest state buffer elements | ++----------+----------+-------------------------------------------+ + +GSB element: + ++----------+----------+-------------------------------------------+ +| Offset | Size | Purpose | +| Bytes | Bytes | | ++==========+==========+===========================================+ +| 0 | 2 | ID | ++----------+----------+-------------------------------------------+ +| 2 | 2 | Size of Value | ++----------+----------+-------------------------------------------+ +| 4 | As above | Value | ++----------+----------+-------------------------------------------+ + +The ID in the GSB element specifies what is to be set. This includes +archtected state like GPRs, VSRs, SPRs, plus also some meta data about +the partition like the timebase offset and partition scoped page +table information. + ++--------+-------+----+--------+----------------------------------+ +| ID | Size | RW | Thread | Details | +| | Bytes | | Guest | | +| | | | Scope | | ++========+=======+====+========+==================================+ +| 0x0000 | | RW | TG | NOP element | ++--------+-------+----+--------+----------------------------------+ +| 0x0001 | 0x08 | R | G | Size of L0 vCPU state. See: | +| | | | | H_GUEST_GET_STATE: | +| | | | | flags = takeOwnershipOfVcpuState | ++--------+-------+----+--------+----------------------------------+ +| 0x0002 | 0x08 | R | G | Size Run vCPU out buffer | ++--------+-------+----+--------+----------------------------------+ +| 0x0003 | 0x04 | RW | G | Logical PVR | ++--------+-------+----+--------+----------------------------------+ +| 0x0004 | 0x08 | RW | G | TB Offset (L1 relative) | ++--------+-------+----+--------+----------------------------------+ +| 0x0005 | 0x18 | RW | G |Partition scoped page tbl info: | +| | | | | | +| | | | |- 0x00 Addr part scope table | +| | | | |- 0x08 Num addr bits | +| | | | |- 0x10 Size root dir | ++--------+-------+----+--------+----------------------------------+ +| 0x0006 | 0x10 | RW | G |Process Table Information: | +| | | | | | +| | | | |- 0x0 Addr proc scope table | +| | | | |- 0x8 Table size. | ++--------+-------+----+--------+----------------------------------+ +| 0x0007-| | | | Reserved | +| 0x0BFF | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x0C00 | 0x10 | RW | T |Run vCPU Input Buffer: | +| | | | | | +| | | | |- 0x0 Addr of buffer | +| | | | |- 0x8 Buffer Size. | ++--------+-------+----+--------+----------------------------------+ +| 0x0C01 | 0x10 | RW | T |Run vCPU Output Buffer: | +| | | | | | +| | | | |- 0x0 Addr of buffer | +| | | | |- 0x8 Buffer Size. | ++--------+-------+----+--------+----------------------------------+ +| 0x0C02 | 0x08 | RW | T | vCPU VPA Address | ++--------+-------+----+--------+----------------------------------+ +| 0x0C03-| | | | Reserved | +| 0x0FFF | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x1000-| 0x08 | RW | T | GPR 0-31 | +| 0x101F | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x1020 | 0x08 | T | T | HDEC expiry TB | ++--------+-------+----+--------+----------------------------------+ +| 0x1021 | 0x08 | RW | T | NIA | ++--------+-------+----+--------+----------------------------------+ +| 0x1022 | 0x08 | RW | T | MSR | ++--------+-------+----+--------+----------------------------------+ +| 0x1023 | 0x08 | RW | T | LR | ++--------+-------+----+--------+----------------------------------+ +| 0x1024 | 0x08 | RW | T | XER | ++--------+-------+----+--------+----------------------------------+ +| 0x1025 | 0x08 | RW | T | CTR | ++--------+-------+----+--------+----------------------------------+ +| 0x1026 | 0x08 | RW | T | CFAR | ++--------+-------+----+--------+----------------------------------+ +| 0x1027 | 0x08 | RW | T | SRR0 | ++--------+-------+----+--------+----------------------------------+ +| 0x1028 | 0x08 | RW | T | SRR1 | ++--------+-------+----+--------+----------------------------------+ +| 0x1029 | 0x08 | RW | T | DAR | ++--------+-------+----+--------+----------------------------------+ +| 0x102A | 0x08 | RW | T | DEC expiry TB | ++--------+-------+----+--------+----------------------------------+ +| 0x102B | 0x08 | RW | T | VTB | ++--------+-------+----+--------+----------------------------------+ +| 0x102C | 0x08 | RW | T | LPCR | ++--------+-------+----+--------+----------------------------------+ +| 0x102D | 0x08 | RW | T | HFSCR | ++--------+-------+----+--------+----------------------------------+ +| 0x102E | 0x08 | RW | T | FSCR | ++--------+-------+----+--------+----------------------------------+ +| 0x102F | 0x08 | RW | T | FPSCR | ++--------+-------+----+--------+----------------------------------+ +| 0x1030 | 0x08 | RW | T | DAWR0 | ++--------+-------+----+--------+----------------------------------+ +| 0x1031 | 0x08 | RW | T | DAWR1 | ++--------+-------+----+--------+----------------------------------+ +| 0x1032 | 0x08 | RW | T | CIABR | ++--------+-------+----+--------+----------------------------------+ +| 0x1033 | 0x08 | RW | T | PURR | ++--------+-------+----+--------+----------------------------------+ +| 0x1034 | 0x08 | RW | T | SPURR | ++--------+-------+----+--------+----------------------------------+ +| 0x1035 | 0x08 | RW | T | IC | ++--------+-------+----+--------+----------------------------------+ +| 0x1036-| 0x08 | RW | T | SPRG 0-3 | +| 0x1039 | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x103A | 0x08 | W | T | PPR | ++--------+-------+----+--------+----------------------------------+ +| 0x103B | 0x08 | RW | T | MMCR 0-3 | +| 0x103E | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x103F | 0x08 | RW | T | MMCRA | ++--------+-------+----+--------+----------------------------------+ +| 0x1040 | 0x08 | RW | T | SIER | ++--------+-------+----+--------+----------------------------------+ +| 0x1041 | 0x08 | RW | T | SIER 2 | ++--------+-------+----+--------+----------------------------------+ +| 0x1042 | 0x08 | RW | T | SIER 3 | ++--------+-------+----+--------+----------------------------------+ +| 0x1043 | 0x08 | RW | T | BESCR | ++--------+-------+----+--------+----------------------------------+ +| 0x1044 | 0x08 | RW | T | EBBHR | ++--------+-------+----+--------+----------------------------------+ +| 0x1045 | 0x08 | RW | T | EBBRR | ++--------+-------+----+--------+----------------------------------+ +| 0x1046 | 0x08 | RW | T | AMR | ++--------+-------+----+--------+----------------------------------+ +| 0x1047 | 0x08 | RW | T | IAMR | ++--------+-------+----+--------+----------------------------------+ +| 0x1048 | 0x08 | RW | T | AMOR | ++--------+-------+----+--------+----------------------------------+ +| 0x1049 | 0x08 | RW | T | UAMOR | ++--------+-------+----+--------+----------------------------------+ +| 0x104A | 0x08 | RW | T | SDAR | ++--------+-------+----+--------+----------------------------------+ +| 0x104B | 0x08 | RW | T | SIAR | ++--------+-------+----+--------+----------------------------------+ +| 0x104C | 0x08 | RW | T | DSCR | ++--------+-------+----+--------+----------------------------------+ +| 0x104D | 0x08 | RW | T | TAR | ++--------+-------+----+--------+----------------------------------+ +| 0x104E | 0x08 | RW | T | DEXCR | ++--------+-------+----+--------+----------------------------------+ +| 0x104F | 0x08 | RW | T | HDEXCR | ++--------+-------+----+--------+----------------------------------+ +| 0x1050 | 0x08 | RW | T | HASHKEYR | ++--------+-------+----+--------+----------------------------------+ +| 0x1051 | 0x08 | RW | T | HASHPKEYR | ++--------+-------+----+--------+----------------------------------+ +| 0x1052 | 0x08 | RW | T | CTRL | ++--------+-------+----+--------+----------------------------------+ +| 0x1053-| | | | Reserved | +| 0x1FFF | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x2000 | 0x04 | RW | T | CR | ++--------+-------+----+--------+----------------------------------+ +| 0x2001 | 0x04 | RW | T | PIDR | ++--------+-------+----+--------+----------------------------------+ +| 0x2002 | 0x04 | RW | T | DSISR | ++--------+-------+----+--------+----------------------------------+ +| 0x2003 | 0x04 | RW | T | VSCR | ++--------+-------+----+--------+----------------------------------+ +| 0x2004 | 0x04 | RW | T | VRSAVE | ++--------+-------+----+--------+----------------------------------+ +| 0x2005 | 0x04 | RW | T | DAWRX0 | ++--------+-------+----+--------+----------------------------------+ +| 0x2006 | 0x04 | RW | T | DAWRX1 | ++--------+-------+----+--------+----------------------------------+ +| 0x2007-| 0x04 | RW | T | PMC 1-6 | +| 0x200c | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x200D | 0x04 | RW | T | WORT | ++--------+-------+----+--------+----------------------------------+ +| 0x200E | 0x04 | RW | T | PSPB | ++--------+-------+----+--------+----------------------------------+ +| 0x200F-| | | | Reserved | +| 0x2FFF | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x3000-| 0x10 | RW | T | VSR 0-63 | +| 0x303F | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0x3040-| | | | Reserved | +| 0xEFFF | | | | | ++--------+-------+----+--------+----------------------------------+ +| 0xF000 | 0x08 | R | T | HDAR | ++--------+-------+----+--------+----------------------------------+ +| 0xF001 | 0x04 | R | T | HDSISR | ++--------+-------+----+--------+----------------------------------+ +| 0xF002 | 0x04 | R | T | HEIR | ++--------+-------+----+--------+----------------------------------+ +| 0xF003 | 0x08 | R | T | ASDR | ++--------+-------+----+--------+----------------------------------+ + + +Miscellaneous info +================== + +State not in ptregs/hvregs +-------------------------- + +In the v1 API, some state is not in the ptregs/hvstate. This includes +the vector register and some SPRs. For the L1 to set this state for +the L2, the L1 loads up these hardware registers before the +h_enter_nested() call and the L0 ensures they end up as the L2 state +(by not touching them). + +The v2 API removes this and explicitly sets this state via the GSB. + +L1 Implementation details: Caching state +---------------------------------------- + +In the v1 API, all state is sent from the L1 to the L0 and vice versa +on every h_enter_nested() hcall. If the L0 is not currently running +any L2s, the L0 has no state information about them. The only +exception to this is the location of the partition table, registered +via h_set_partition_table(). + +The v2 API changes this so that the L0 retains the L2 state even when +it's vCPUs are no longer running. This means that the L1 only needs to +communicate with the L0 about L2 state when it needs to modify the L2 +state, or when it's value is out of date. This provides an opportunity +for performance optimisation. + +When a vCPU exits from a H_GUEST_RUN_VCPU() call, the L1 internally +marks all L2 state as invalid. This means that if the L1 wants to know +the L2 state (say via a kvm_get_one_reg() call), it needs call +H_GUEST_GET_STATE() to get that state. Once it's read, it's marked as +valid in L1 until the L2 is run again. + +Also, when an L1 modifies L2 vcpu state, it doesn't need to write it +to the L0 until that L2 vcpu runs again. Hence when the L1 updates +state (say via a kvm_set_one_reg() call), it writes to an internal L1 +copy and only flushes this copy to the L0 when the L2 runs again via +the H_GUEST_VCPU_RUN() input buffer. + +This lazy updating of state by the L1 avoids unnecessary +H_GUEST_{G|S}ET_STATE() calls. diff --git a/Documentation/trace/user_events.rst b/Documentation/trace/user_events.rst index f9530d0ac5d3..d8f12442aaa6 100644 --- a/Documentation/trace/user_events.rst +++ b/Documentation/trace/user_events.rst @@ -14,6 +14,11 @@ Programs can view status of the events via /sys/kernel/tracing/user_events_status and can both register and write data out via /sys/kernel/tracing/user_events_data. +Programs can also use /sys/kernel/tracing/dynamic_events to register and +delete user based events via the u: prefix. The format of the command to +dynamic_events is the same as the ioctl with the u: prefix applied. This +requires CAP_PERFMON due to the event persisting, otherwise -EPERM is returned. + Typically programs will register a set of events that they wish to expose to tools that can read trace_events (such as ftrace and perf). The registration process tells the kernel which address and bit to reflect if any tool has @@ -45,7 +50,7 @@ This command takes a packed struct user_reg as an argument:: /* Input: Enable size in bytes at address */ __u8 enable_size; - /* Input: Flags for future use, set to 0 */ + /* Input: Flags to use, if any */ __u16 flags; /* Input: Address to update when enabled */ @@ -69,7 +74,7 @@ The struct user_reg requires all the above inputs to be set appropriately. This must be 4 (32-bit) or 8 (64-bit). 64-bit values are only allowed to be used on 64-bit kernels, however, 32-bit can be used on all kernels. -+ flags: The flags to use, if any. For the initial version this must be 0. ++ flags: The flags to use, if any. Callers should first attempt to use flags and retry without flags to ensure support for lower versions of the kernel. If a flag is not supported -EINVAL is returned. @@ -80,6 +85,13 @@ The struct user_reg requires all the above inputs to be set appropriately. + name_args: The name and arguments to describe the event, see command format for details. +The following flags are currently supported. + ++ USER_EVENT_REG_PERSIST: The event will not delete upon the last reference + closing. Callers may use this if an event should exist even after the + process closes or unregisters the event. Requires CAP_PERFMON otherwise + -EPERM is returned. + Upon successful registration the following is set. + write_index: The index to use for this file descriptor that represents this @@ -141,7 +153,10 @@ event (in both user and kernel space). User programs should use a separate file to request deletes than the one used for registration due to this. **NOTE:** By default events will auto-delete when there are no references left -to the event. Flags in the future may change this logic. +to the event. If programs do not want auto-delete, they must use the +USER_EVENT_REG_PERSIST flag when registering the event. Once that flag is used +the event exists until DIAG_IOCSDEL is invoked. Both register and delete of an +event that persists requires CAP_PERFMON, otherwise -EPERM is returned. Unregistering ------------- diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst index d8cd8cd9ce25..2e3822677061 100644 --- a/Documentation/userspace-api/landlock.rst +++ b/Documentation/userspace-api/landlock.rst @@ -8,13 +8,13 @@ Landlock: unprivileged access control ===================================== :Author: Mickaël Salaün -:Date: October 2022 +:Date: October 2023 The goal of Landlock is to enable to restrict ambient rights (e.g. global -filesystem access) for a set of processes. Because Landlock is a stackable -LSM, it makes possible to create safe security sandboxes as new security layers -in addition to the existing system-wide access-controls. This kind of sandbox -is expected to help mitigate the security impact of bugs or +filesystem or network access) for a set of processes. Because Landlock +is a stackable LSM, it makes possible to create safe security sandboxes as new +security layers in addition to the existing system-wide access-controls. This +kind of sandbox is expected to help mitigate the security impact of bugs or unexpected/malicious behaviors in user space applications. Landlock empowers any process, including unprivileged ones, to securely restrict themselves. @@ -28,20 +28,34 @@ appropriately `. Landlock rules ============== -A Landlock rule describes an action on an object. An object is currently a -file hierarchy, and the related filesystem actions are defined with `access -rights`_. A set of rules is aggregated in a ruleset, which can then restrict +A Landlock rule describes an action on an object which the process intends to +perform. A set of rules is aggregated in a ruleset, which can then restrict the thread enforcing it, and its future children. +The two existing types of rules are: + +Filesystem rules + For these rules, the object is a file hierarchy, + and the related filesystem actions are defined with + `filesystem access rights`. + +Network rules (since ABI v4) + For these rules, the object is a TCP port, + and the related actions are defined with `network access rights`. + Defining and enforcing a security policy ---------------------------------------- -We first need to define the ruleset that will contain our rules. For this -example, the ruleset will contain rules that only allow read actions, but write -actions will be denied. The ruleset then needs to handle both of these kind of -actions. This is required for backward and forward compatibility (i.e. the -kernel and user space may not know each other's supported restrictions), hence -the need to be explicit about the denied-by-default access rights. +We first need to define the ruleset that will contain our rules. + +For this example, the ruleset will contain rules that only allow filesystem +read actions and establish a specific TCP connection. Filesystem write +actions and other TCP actions will be denied. + +The ruleset then needs to handle both these kinds of actions. This is +required for backward and forward compatibility (i.e. the kernel and user +space may not know each other's supported restrictions), hence the need +to be explicit about the denied-by-default access rights. .. code-block:: c @@ -62,6 +76,9 @@ the need to be explicit about the denied-by-default access rights. LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_TRUNCATE, + .handled_access_net = + LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, }; Because we may not know on which kernel version an application will be @@ -70,9 +87,7 @@ should try to protect users as much as possible whatever the kernel they are using. To avoid binary enforcement (i.e. either all security features or none), we can leverage a dedicated Landlock command to get the current version of the Landlock ABI and adapt the handled accesses. Let's check if we should -remove the ``LANDLOCK_ACCESS_FS_REFER`` or ``LANDLOCK_ACCESS_FS_TRUNCATE`` -access rights, which are only supported starting with the second and third -version of the ABI. +remove access rights which are only supported in higher versions of the ABI. .. code-block:: c @@ -92,6 +107,12 @@ version of the ABI. case 2: /* Removes LANDLOCK_ACCESS_FS_TRUNCATE for ABI < 3 */ ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE; + __attribute__((fallthrough)); + case 3: + /* Removes network support for ABI < 4 */ + ruleset_attr.handled_access_net &= + ~(LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP); } This enables to create an inclusive ruleset that will contain our rules. @@ -143,10 +164,23 @@ for the ruleset creation, by filtering access rights according to the Landlock ABI version. In this example, this is not required because all of the requested ``allowed_access`` rights are already available in ABI 1. -We now have a ruleset with one rule allowing read access to ``/usr`` while -denying all other handled accesses for the filesystem. The next step is to -restrict the current thread from gaining more privileges (e.g. thanks to a SUID -binary). +For network access-control, we can add a set of rules that allow to use a port +number for a specific action: HTTPS connections. + +.. code-block:: c + + struct landlock_net_port_attr net_port = { + .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = 443, + }; + + err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &net_port, 0); + +The next step is to restrict the current thread from gaining more privileges +(e.g. through a SUID binary). We now have a ruleset with the first rule +allowing read access to ``/usr`` while denying all other handled accesses for +the filesystem, and a second rule allowing HTTPS connections. .. code-block:: c @@ -355,7 +389,7 @@ Access rights ------------- .. kernel-doc:: include/uapi/linux/landlock.h - :identifiers: fs_access + :identifiers: fs_access net_access Creating a new ruleset ---------------------- @@ -374,6 +408,7 @@ Extending a ruleset .. kernel-doc:: include/uapi/linux/landlock.h :identifiers: landlock_rule_type landlock_path_beneath_attr + landlock_net_port_attr Enforcing a ruleset ------------------- @@ -387,9 +422,9 @@ Current limitations Filesystem topology modification -------------------------------- -As for file renaming and linking, a sandboxed thread cannot modify its -filesystem topology, whether via :manpage:`mount(2)` or -:manpage:`pivot_root(2)`. However, :manpage:`chroot(2)` calls are not denied. +Threads sandboxed with filesystem restrictions cannot modify filesystem +topology, whether via :manpage:`mount(2)` or :manpage:`pivot_root(2)`. +However, :manpage:`chroot(2)` calls are not denied. Special filesystems ------------------- @@ -451,6 +486,14 @@ always allowed when using a kernel that only supports the first or second ABI. Starting with the Landlock ABI version 3, it is now possible to securely control truncation thanks to the new ``LANDLOCK_ACCESS_FS_TRUNCATE`` access right. +Network support (ABI < 4) +------------------------- + +Starting with the Landlock ABI version 4, it is now possible to restrict TCP +bind and connect actions to only a set of allowed ports thanks to the new +``LANDLOCK_ACCESS_NET_BIND_TCP`` and ``LANDLOCK_ACCESS_NET_CONNECT_TCP`` +access rights. + .. _kernel_support: Kernel support @@ -469,6 +512,12 @@ still enable it by adding ``lsm=landlock,[...]`` to Documentation/admin-guide/kernel-parameters.rst thanks to the bootloader configuration. +To be able to explicitly allow TCP operations (e.g., adding a network rule with +``LANDLOCK_ACCESS_NET_BIND_TCP``), the kernel must support TCP +(``CONFIG_INET=y``). Otherwise, sys_landlock_add_rule() returns an +``EAFNOSUPPORT`` error, which can safely be ignored because this kind of TCP +operation is already not possible. + Questions and answers ===================== diff --git a/MAINTAINERS b/MAINTAINERS index 152dbf4ab367..d62e7d323273 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3539,12 +3539,14 @@ R: Andy Shevchenko R: Rasmus Villemoes S: Maintained F: include/linux/bitfield.h +F: include/linux/bitmap-str.h F: include/linux/bitmap.h F: include/linux/bits.h F: include/linux/cpumask.h F: include/linux/find.h F: include/linux/nodemask.h F: include/vdso/bits.h +F: lib/bitmap-str.c F: lib/bitmap.c F: lib/cpumask.c F: lib/cpumask_kunit.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index d5d5388973ac..6f105ee4f3cf 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -237,6 +237,7 @@ config PPC select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_FAST_GUP select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_FUNCTION_ARG_ACCESS_API select HAVE_FUNCTION_DESCRIPTORS if PPC64_ELF_ABI_V1 select HAVE_FUNCTION_ERROR_INJECTION select HAVE_FUNCTION_GRAPH_TRACER diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 2a54fadbeaf5..ea4033abc07d 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -82,6 +82,18 @@ config MSI_BITMAP_SELFTEST bool "Run self-tests of the MSI bitmap code" depends on DEBUG_KERNEL +config GUEST_STATE_BUFFER_TEST + def_tristate n + prompt "Enable Guest State Buffer unit tests" + depends on KUNIT + depends on KVM_BOOK3S_HV_POSSIBLE + default KUNIT_ALL_TESTS + help + The Guest State Buffer is a data format specified in the PAPR. + It is by hcalls to communicate the state of L2 guests between + the L1 and L0 hypervisors. Enable unit tests for the library + used to create and use guest state buffers. + config PPC_IRQ_SOFT_MASK_DEBUG bool "Include extra checks for powerpc irq soft masking" depends on PPC64 @@ -147,6 +159,8 @@ config BDI_SWITCH config BOOTX_TEXT bool "Support for early boot text console (BootX or OpenFirmware only)" depends on PPC_BOOK3S + select FONT_SUN8x16 + select FONT_SUPPORT help Say Y here to see progress messages from the boot firmware in text mode. Requires either BootX or Open Firmware. diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh index 461902c8a46d..101fcb397a0f 100755 --- a/arch/powerpc/boot/install.sh +++ b/arch/powerpc/boot/install.sh @@ -21,13 +21,17 @@ set -e # this should work for both the pSeries zImage and the iSeries vmlinux.sm image_name=`basename $2` -if [ -f $4/$image_name ]; then - mv $4/$image_name $4/$image_name.old + +echo "Warning: '${INSTALLKERNEL}' command not available... Copying" \ + "directly to $4/$image_name-$1" >&2 + +if [ -f $4/$image_name-$1 ]; then + mv $4/$image_name-$1 $4/$image_name-$1.old fi -if [ -f $4/System.map ]; then - mv $4/System.map $4/System.old +if [ -f $4/System.map-$1 ]; then + mv $4/System.map-$1 $4/System-$1.old fi -cat $2 > $4/$image_name -cp $3 $4/System.map +cat $2 > $4/$image_name-$1 +cp $3 $4/System.map-$1 diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig index 51499ee6366b..2479ab62d12f 100644 --- a/arch/powerpc/configs/44x/sam440ep_defconfig +++ b/arch/powerpc/configs/44x/sam440ep_defconfig @@ -78,7 +78,6 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_REISERFS_FS=y CONFIG_AUTOFS_FS=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y diff --git a/arch/powerpc/configs/debug.config b/arch/powerpc/configs/debug.config index a14ae1f20d60..bcc1fcf25e10 100644 --- a/arch/powerpc/configs/debug.config +++ b/arch/powerpc/configs/debug.config @@ -1 +1,5 @@ +CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG=y +CONFIG_PPC_IRQ_SOFT_MASK_DEBUG=y +CONFIG_PPC_KUAP_DEBUG=y +CONFIG_PPC_RFI_SRR_DEBUG=y CONFIG_SCOM_DEBUGFS=y diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 71d9d112c0b6..9215bed53291 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -202,10 +202,6 @@ CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y -CONFIG_REISERFS_FS=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y CONFIG_XFS_FS=m CONFIG_XFS_POSIX_ACL=y CONFIG_FS_DAX=y diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index a205da9ee5f2..57ded82c2840 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig @@ -138,7 +138,6 @@ CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_ADB=y -CONFIG_ADB_CUDA=y CONFIG_ADB_PMU=y CONFIG_ADB_PMU_LED=y CONFIG_ADB_PMU_LED_DISK=y @@ -181,6 +180,7 @@ CONFIG_SERIAL_PMACZILOG_TTYS=y CONFIG_SERIAL_PMACZILOG_CONSOLE=y CONFIG_NVRAM=y CONFIG_I2C_CHARDEV=m +CONFIG_POWER_RESET=y CONFIG_APM_POWER=y CONFIG_BATTERY_PMU=y CONFIG_HWMON=m diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 624c371ffcc3..4c05f4e4d505 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig @@ -175,10 +175,6 @@ CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y -CONFIG_REISERFS_FS=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y CONFIG_JFS_FS=y CONFIG_JFS_POSIX_ACL=y CONFIG_JFS_SECURITY=y diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index eaf3273372a9..f279703425d4 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -954,11 +954,6 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y CONFIG_JBD2_DEBUG=y -CONFIG_REISERFS_FS=m -CONFIG_REISERFS_PROC_INFO=y -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y CONFIG_JFS_FS=m CONFIG_JFS_POSIX_ACL=y CONFIG_JFS_SECURITY=y diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 9b13eb14e21b..52971ee30717 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -20,7 +20,7 @@ #define _PAGE_PRESENT 0x001 /* software: pte contains a translation */ #define _PAGE_HASHPTE 0x002 /* hash_page has made an HPTE for this pte */ -#define _PAGE_USER 0x004 /* usermode access allowed */ +#define _PAGE_READ 0x004 /* software: read access allowed */ #define _PAGE_GUARDED 0x008 /* G: prohibit speculative access */ #define _PAGE_COHERENT 0x010 /* M: enforce memory coherence (SMP systems) */ #define _PAGE_NO_CACHE 0x020 /* I: cache inhibit */ @@ -28,7 +28,7 @@ #define _PAGE_DIRTY 0x080 /* C: page changed */ #define _PAGE_ACCESSED 0x100 /* R: page referenced */ #define _PAGE_EXEC 0x200 /* software: exec allowed */ -#define _PAGE_RW 0x400 /* software: user write access allowed */ +#define _PAGE_WRITE 0x400 /* software: user write access allowed */ #define _PAGE_SPECIAL 0x800 /* software: Special page */ #ifdef CONFIG_PTE_64BIT @@ -42,26 +42,13 @@ #define _PMD_PRESENT_MASK (PAGE_MASK) #define _PMD_BAD (~PAGE_MASK) -/* We borrow the _PAGE_USER bit to store the exclusive marker in swap PTEs. */ -#define _PAGE_SWP_EXCLUSIVE _PAGE_USER +/* We borrow the _PAGE_READ bit to store the exclusive marker in swap PTEs. */ +#define _PAGE_SWP_EXCLUSIVE _PAGE_READ /* And here we include common definitions */ -#define _PAGE_KERNEL_RO 0 -#define _PAGE_KERNEL_ROX (_PAGE_EXEC) -#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) -#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) - #define _PAGE_HPTEFLAGS _PAGE_HASHPTE -#ifndef __ASSEMBLY__ - -static inline bool pte_user(pte_t pte) -{ - return pte_val(pte) & _PAGE_USER; -} -#endif /* __ASSEMBLY__ */ - /* * Location of the PFN in the PTE. Most 32-bit platforms use the same * as _PAGE_SHIFT here (ie, naturally aligned). @@ -97,20 +84,7 @@ static inline bool pte_user(pte_t pte) #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) -/* - * Permission masks used to generate the __P and __S table. - * - * Note:__pgprot is defined in arch/powerpc/include/asm/page.h - * - * Write permissions imply read permissions for now. - */ -#define PAGE_NONE __pgprot(_PAGE_BASE) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#include /* Permission masks used for kernel mappings */ #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) @@ -170,7 +144,14 @@ void unmap_kernel_page(unsigned long va); * value (for now) on others, from where we can start layout kernel * virtual space that goes below PKMAP and FIXMAP */ -#include + +#define FIXADDR_SIZE 0 +#ifdef CONFIG_KASAN +#include +#define FIXADDR_TOP (KASAN_SHADOW_START - PAGE_SIZE) +#else +#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE)) +#endif /* * ioremap_bot starts at that address. Early ioremaps move down from there, @@ -224,9 +205,6 @@ void unmap_kernel_page(unsigned long va); /* Bits to mask out from a PGD to get to the PUD page */ #define PGD_MASKED_BITS 0 -#define pte_ERROR(e) \ - pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \ - (unsigned long long)pte_val(e)) #define pgd_ERROR(e) \ pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) /* @@ -343,7 +321,7 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); + pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0); } static inline void __ptep_set_access_flags(struct vm_area_struct *vma, @@ -402,8 +380,16 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) } /* Generic accessors to PTE bits */ -static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);} -static inline int pte_read(pte_t pte) { return 1; } +static inline bool pte_read(pte_t pte) +{ + return !!(pte_val(pte) & _PAGE_READ); +} + +static inline bool pte_write(pte_t pte) +{ + return !!(pte_val(pte) & _PAGE_WRITE); +} + static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY); } static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); } static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); } @@ -438,10 +424,10 @@ static inline bool pte_ci(pte_t pte) static inline bool pte_access_permitted(pte_t pte, bool write) { /* - * A read-only access is controlled by _PAGE_USER bit. - * We have _PAGE_READ set for WRITE and EXECUTE + * A read-only access is controlled by _PAGE_READ bit. + * We have _PAGE_READ set for WRITE */ - if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) + if (!pte_present(pte) || !pte_read(pte)) return false; if (write && !pte_write(pte)) @@ -465,7 +451,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) /* Generic modifiers for PTE bits */ static inline pte_t pte_wrprotect(pte_t pte) { - return __pte(pte_val(pte) & ~_PAGE_RW); + return __pte(pte_val(pte) & ~_PAGE_WRITE); } static inline pte_t pte_exprotect(pte_t pte) @@ -495,6 +481,9 @@ static inline pte_t pte_mkpte(pte_t pte) static inline pte_t pte_mkwrite_novma(pte_t pte) { + /* + * write implies read, hence set both + */ return __pte(pte_val(pte) | _PAGE_RW); } @@ -518,16 +507,6 @@ static inline pte_t pte_mkhuge(pte_t pte) return pte; } -static inline pte_t pte_mkprivileged(pte_t pte) -{ - return __pte(pte_val(pte) & ~_PAGE_USER); -} - -static inline pte_t pte_mkuser(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_USER); -} - static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); diff --git a/arch/powerpc/include/asm/book3s/32/tlbflush.h b/arch/powerpc/include/asm/book3s/32/tlbflush.h index 4be572908124..e43534da5207 100644 --- a/arch/powerpc/include/asm/book3s/32/tlbflush.h +++ b/arch/powerpc/include/asm/book3s/32/tlbflush.h @@ -80,7 +80,7 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma, static inline void local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, int psize) { - BUILD_BUG(); + flush_range(mm, vmaddr, vmaddr); } static inline void local_flush_tlb_mm(struct mm_struct *mm) diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 5c497c862d75..cb77eddca54b 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -17,6 +17,10 @@ #define _PAGE_EXEC 0x00001 /* execute permission */ #define _PAGE_WRITE 0x00002 /* write access allowed */ #define _PAGE_READ 0x00004 /* read access allowed */ +#define _PAGE_NA _PAGE_PRIVILEGED +#define _PAGE_NAX _PAGE_EXEC +#define _PAGE_RO _PAGE_READ +#define _PAGE_ROX (_PAGE_READ | _PAGE_EXEC) #define _PAGE_RW (_PAGE_READ | _PAGE_WRITE) #define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC) #define _PAGE_PRIVILEGED 0x00008 /* kernel access only */ @@ -136,23 +140,7 @@ #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) #define _PAGE_BASE (_PAGE_BASE_NC) -/* Permission masks used to generate the __P and __S table, - * - * Note:__pgprot is defined in arch/powerpc/include/asm/page.h - * - * Write permissions imply read permissions for now (we could make write-only - * pages on BookE but we don't bother for now). Execute permission control is - * possible on platforms that define _PAGE_EXEC - */ -#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_PRIVILEGED) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_READ) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) -/* Radix only, Hash uses PAGE_READONLY_X + execute-only pkey instead */ -#define PAGE_EXECONLY __pgprot(_PAGE_BASE | _PAGE_EXEC) +#include /* Permission masks used for kernel mappings */ #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) @@ -316,6 +304,7 @@ extern unsigned long pci_io_base; #define IOREMAP_START (ioremap_bot) #define IOREMAP_END (KERN_IO_END - FIXADDR_SIZE) #define FIXADDR_SIZE SZ_32M +#define FIXADDR_TOP (IOREMAP_END + FIXADDR_SIZE) #ifndef __ASSEMBLY__ @@ -629,16 +618,6 @@ static inline pte_t pte_mkdevmap(pte_t pte) return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL | _PAGE_DEVMAP)); } -static inline pte_t pte_mkprivileged(pte_t pte) -{ - return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); -} - -static inline pte_t pte_mkuser(pte_t pte) -{ - return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); -} - /* * This is potentially called with a pmd as the argument, in which case it's not * safe to check _PAGE_DEVMAP unless we also confirm that _PAGE_PTE is set. @@ -647,7 +626,7 @@ static inline pte_t pte_mkuser(pte_t pte) */ static inline int pte_devmap(pte_t pte) { - u64 mask = cpu_to_be64(_PAGE_DEVMAP | _PAGE_PTE); + __be64 mask = cpu_to_be64(_PAGE_DEVMAP | _PAGE_PTE); return (pte_raw(pte) & mask) == mask; } @@ -1014,8 +993,6 @@ static inline pmd_t *pud_pgtable(pud_t pud) return (pmd_t *)__va(pud_val(pud) & ~PUD_MASKED_BITS); } -#define pte_ERROR(e) \ - pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) #define pud_ERROR(e) \ diff --git a/arch/powerpc/include/asm/book3s/pgtable.h b/arch/powerpc/include/asm/book3s/pgtable.h index 3b7bd36a2321..f42d68c6b314 100644 --- a/arch/powerpc/include/asm/book3s/pgtable.h +++ b/arch/powerpc/include/asm/book3s/pgtable.h @@ -8,37 +8,4 @@ #include #endif -#ifndef __ASSEMBLY__ -#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, - pte_t *ptep, pte_t entry, int dirty); - -struct file; -extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, - unsigned long size, pgprot_t vma_prot); -#define __HAVE_PHYS_MEM_ACCESS_PROT - -void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep); - -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to ensure coherency between the i-cache and d-cache - * for the page which has just been mapped in. - * On machines which use an MMU hash table, we use this to put a - * corresponding HPTE into the hash table ahead of time, instead of - * waiting for the inevitable extra hash-table miss exception. - */ -static inline void update_mmu_cache_range(struct vm_fault *vmf, - struct vm_area_struct *vma, unsigned long address, - pte_t *ptep, unsigned int nr) -{ - if (IS_ENABLED(CONFIG_PPC32) && !mmu_has_feature(MMU_FTR_HPTE_TABLE)) - return; - if (radix_enabled()) - return; - __update_mmu_cache(vma, address, ptep); -} - -#endif /* __ASSEMBLY__ */ #endif diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h index 3f881548fb61..0e29ccf903d0 100644 --- a/arch/powerpc/include/asm/code-patching.h +++ b/arch/powerpc/include/asm/code-patching.h @@ -74,6 +74,7 @@ int create_cond_branch(ppc_inst_t *instr, const u32 *addr, int patch_branch(u32 *addr, unsigned long target, int flags); int patch_instruction(u32 *addr, ppc_inst_t instr); int raw_patch_instruction(u32 *addr, ppc_inst_t instr); +int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr); static inline unsigned long patch_site_addr(s32 *site) { diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 3bdd74739cb8..e3c6969853ef 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h @@ -49,11 +49,6 @@ */ extern cpm8xx_t __iomem *cpmp; /* Pointer to comm processor */ -#define cpm_dpalloc cpm_muram_alloc -#define cpm_dpfree cpm_muram_free -#define cpm_dpram_addr cpm_muram_addr -#define cpm_dpram_phys cpm_muram_dma - extern void cpm_setbrg(uint brg, uint rate); extern void __init cpm_load_patch(cpm8xx_t *cp); diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h index 249d43cc6427..a22acc36eb9b 100644 --- a/arch/powerpc/include/asm/cpm2.h +++ b/arch/powerpc/include/asm/cpm2.h @@ -87,10 +87,6 @@ */ extern cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor */ -#define cpm_dpalloc cpm_muram_alloc -#define cpm_dpfree cpm_muram_free -#define cpm_dpram_addr cpm_muram_addr - extern void cpm2_reset(void); /* Baud rate generators. diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h index a832aeafe560..f9068dd8dfce 100644 --- a/arch/powerpc/include/asm/fixmap.h +++ b/arch/powerpc/include/asm/fixmap.h @@ -23,18 +23,6 @@ #include #endif -#ifdef CONFIG_PPC64 -#define FIXADDR_TOP (IOREMAP_END + FIXADDR_SIZE) -#else -#define FIXADDR_SIZE 0 -#ifdef CONFIG_KASAN -#include -#define FIXADDR_TOP (KASAN_SHADOW_START - PAGE_SIZE) -#else -#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE)) -#endif -#endif - /* * Here we define all the compile-time 'special' virtual * addresses. The point is to have a constant address at @@ -119,5 +107,9 @@ static inline void __set_fixmap(enum fixed_addresses idx, #define __early_set_fixmap __set_fixmap +#ifdef CONFIG_PPC_8xx +#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE)) +#endif + #endif /* !__ASSEMBLY__ */ #endif diff --git a/arch/powerpc/include/asm/guest-state-buffer.h b/arch/powerpc/include/asm/guest-state-buffer.h new file mode 100644 index 000000000000..808149f31576 --- /dev/null +++ b/arch/powerpc/include/asm/guest-state-buffer.h @@ -0,0 +1,995 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Interface based on include/net/netlink.h + */ +#ifndef _ASM_POWERPC_GUEST_STATE_BUFFER_H +#define _ASM_POWERPC_GUEST_STATE_BUFFER_H + +#include "asm/hvcall.h" +#include +#include +#include + +/************************************************************************** + * Guest State Buffer Constants + **************************************************************************/ +/* Element without a value and any length */ +#define KVMPPC_GSID_BLANK 0x0000 +/* Size required for the L0's internal VCPU representation */ +#define KVMPPC_GSID_HOST_STATE_SIZE 0x0001 + /* Minimum size for the H_GUEST_RUN_VCPU output buffer */ +#define KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE 0x0002 + /* "Logical" PVR value as defined in the PAPR */ +#define KVMPPC_GSID_LOGICAL_PVR 0x0003 + /* L0 relative timebase offset */ +#define KVMPPC_GSID_TB_OFFSET 0x0004 + /* Partition Scoped Page Table Info */ +#define KVMPPC_GSID_PARTITION_TABLE 0x0005 + /* Process Table Info */ +#define KVMPPC_GSID_PROCESS_TABLE 0x0006 + +/* H_GUEST_RUN_VCPU input buffer Info */ +#define KVMPPC_GSID_RUN_INPUT 0x0C00 +/* H_GUEST_RUN_VCPU output buffer Info */ +#define KVMPPC_GSID_RUN_OUTPUT 0x0C01 +#define KVMPPC_GSID_VPA 0x0C02 + +#define KVMPPC_GSID_GPR(x) (0x1000 + (x)) +#define KVMPPC_GSID_HDEC_EXPIRY_TB 0x1020 +#define KVMPPC_GSID_NIA 0x1021 +#define KVMPPC_GSID_MSR 0x1022 +#define KVMPPC_GSID_LR 0x1023 +#define KVMPPC_GSID_XER 0x1024 +#define KVMPPC_GSID_CTR 0x1025 +#define KVMPPC_GSID_CFAR 0x1026 +#define KVMPPC_GSID_SRR0 0x1027 +#define KVMPPC_GSID_SRR1 0x1028 +#define KVMPPC_GSID_DAR 0x1029 +#define KVMPPC_GSID_DEC_EXPIRY_TB 0x102A +#define KVMPPC_GSID_VTB 0x102B +#define KVMPPC_GSID_LPCR 0x102C +#define KVMPPC_GSID_HFSCR 0x102D +#define KVMPPC_GSID_FSCR 0x102E +#define KVMPPC_GSID_FPSCR 0x102F +#define KVMPPC_GSID_DAWR0 0x1030 +#define KVMPPC_GSID_DAWR1 0x1031 +#define KVMPPC_GSID_CIABR 0x1032 +#define KVMPPC_GSID_PURR 0x1033 +#define KVMPPC_GSID_SPURR 0x1034 +#define KVMPPC_GSID_IC 0x1035 +#define KVMPPC_GSID_SPRG0 0x1036 +#define KVMPPC_GSID_SPRG1 0x1037 +#define KVMPPC_GSID_SPRG2 0x1038 +#define KVMPPC_GSID_SPRG3 0x1039 +#define KVMPPC_GSID_PPR 0x103A +#define KVMPPC_GSID_MMCR(x) (0x103B + (x)) +#define KVMPPC_GSID_MMCRA 0x103F +#define KVMPPC_GSID_SIER(x) (0x1040 + (x)) +#define KVMPPC_GSID_BESCR 0x1043 +#define KVMPPC_GSID_EBBHR 0x1044 +#define KVMPPC_GSID_EBBRR 0x1045 +#define KVMPPC_GSID_AMR 0x1046 +#define KVMPPC_GSID_IAMR 0x1047 +#define KVMPPC_GSID_AMOR 0x1048 +#define KVMPPC_GSID_UAMOR 0x1049 +#define KVMPPC_GSID_SDAR 0x104A +#define KVMPPC_GSID_SIAR 0x104B +#define KVMPPC_GSID_DSCR 0x104C +#define KVMPPC_GSID_TAR 0x104D +#define KVMPPC_GSID_DEXCR 0x104E +#define KVMPPC_GSID_HDEXCR 0x104F +#define KVMPPC_GSID_HASHKEYR 0x1050 +#define KVMPPC_GSID_HASHPKEYR 0x1051 +#define KVMPPC_GSID_CTRL 0x1052 + +#define KVMPPC_GSID_CR 0x2000 +#define KVMPPC_GSID_PIDR 0x2001 +#define KVMPPC_GSID_DSISR 0x2002 +#define KVMPPC_GSID_VSCR 0x2003 +#define KVMPPC_GSID_VRSAVE 0x2004 +#define KVMPPC_GSID_DAWRX0 0x2005 +#define KVMPPC_GSID_DAWRX1 0x2006 +#define KVMPPC_GSID_PMC(x) (0x2007 + (x)) +#define KVMPPC_GSID_WORT 0x200D +#define KVMPPC_GSID_PSPB 0x200E + +#define KVMPPC_GSID_VSRS(x) (0x3000 + (x)) + +#define KVMPPC_GSID_HDAR 0xF000 +#define KVMPPC_GSID_HDSISR 0xF001 +#define KVMPPC_GSID_HEIR 0xF002 +#define KVMPPC_GSID_ASDR 0xF003 + +#define KVMPPC_GSE_GUESTWIDE_START KVMPPC_GSID_BLANK +#define KVMPPC_GSE_GUESTWIDE_END KVMPPC_GSID_PROCESS_TABLE +#define KVMPPC_GSE_GUESTWIDE_COUNT \ + (KVMPPC_GSE_GUESTWIDE_END - KVMPPC_GSE_GUESTWIDE_START + 1) + +#define KVMPPC_GSE_META_START KVMPPC_GSID_RUN_INPUT +#define KVMPPC_GSE_META_END KVMPPC_GSID_VPA +#define KVMPPC_GSE_META_COUNT (KVMPPC_GSE_META_END - KVMPPC_GSE_META_START + 1) + +#define KVMPPC_GSE_DW_REGS_START KVMPPC_GSID_GPR(0) +#define KVMPPC_GSE_DW_REGS_END KVMPPC_GSID_CTRL +#define KVMPPC_GSE_DW_REGS_COUNT \ + (KVMPPC_GSE_DW_REGS_END - KVMPPC_GSE_DW_REGS_START + 1) + +#define KVMPPC_GSE_W_REGS_START KVMPPC_GSID_CR +#define KVMPPC_GSE_W_REGS_END KVMPPC_GSID_PSPB +#define KVMPPC_GSE_W_REGS_COUNT \ + (KVMPPC_GSE_W_REGS_END - KVMPPC_GSE_W_REGS_START + 1) + +#define KVMPPC_GSE_VSRS_START KVMPPC_GSID_VSRS(0) +#define KVMPPC_GSE_VSRS_END KVMPPC_GSID_VSRS(63) +#define KVMPPC_GSE_VSRS_COUNT (KVMPPC_GSE_VSRS_END - KVMPPC_GSE_VSRS_START + 1) + +#define KVMPPC_GSE_INTR_REGS_START KVMPPC_GSID_HDAR +#define KVMPPC_GSE_INTR_REGS_END KVMPPC_GSID_ASDR +#define KVMPPC_GSE_INTR_REGS_COUNT \ + (KVMPPC_GSE_INTR_REGS_END - KVMPPC_GSE_INTR_REGS_START + 1) + +#define KVMPPC_GSE_IDEN_COUNT \ + (KVMPPC_GSE_GUESTWIDE_COUNT + KVMPPC_GSE_META_COUNT + \ + KVMPPC_GSE_DW_REGS_COUNT + KVMPPC_GSE_W_REGS_COUNT + \ + KVMPPC_GSE_VSRS_COUNT + KVMPPC_GSE_INTR_REGS_COUNT) + +/** + * Ranges of guest state buffer elements + */ +enum { + KVMPPC_GS_CLASS_GUESTWIDE = 0x01, + KVMPPC_GS_CLASS_META = 0x02, + KVMPPC_GS_CLASS_DWORD_REG = 0x04, + KVMPPC_GS_CLASS_WORD_REG = 0x08, + KVMPPC_GS_CLASS_VECTOR = 0x10, + KVMPPC_GS_CLASS_INTR = 0x20, +}; + +/** + * Types of guest state buffer elements + */ +enum { + KVMPPC_GSE_BE32, + KVMPPC_GSE_BE64, + KVMPPC_GSE_VEC128, + KVMPPC_GSE_PARTITION_TABLE, + KVMPPC_GSE_PROCESS_TABLE, + KVMPPC_GSE_BUFFER, + __KVMPPC_GSE_TYPE_MAX, +}; + +/** + * Flags for guest state elements + */ +enum { + KVMPPC_GS_FLAGS_WIDE = 0x01, +}; + +/** + * struct kvmppc_gs_part_table - deserialized partition table information + * element + * @address: start of the partition table + * @ea_bits: number of bits in the effective address + * @gpd_size: root page directory size + */ +struct kvmppc_gs_part_table { + u64 address; + u64 ea_bits; + u64 gpd_size; +}; + +/** + * struct kvmppc_gs_proc_table - deserialized process table information element + * @address: start of the process table + * @gpd_size: process table size + */ +struct kvmppc_gs_proc_table { + u64 address; + u64 gpd_size; +}; + +/** + * struct kvmppc_gs_buff_info - deserialized meta guest state buffer information + * @address: start of the guest state buffer + * @size: size of the guest state buffer + */ +struct kvmppc_gs_buff_info { + u64 address; + u64 size; +}; + +/** + * struct kvmppc_gs_header - serialized guest state buffer header + * @nelem: count of guest state elements in the buffer + * @data: start of the stream of elements in the buffer + */ +struct kvmppc_gs_header { + __be32 nelems; + char data[]; +} __packed; + +/** + * struct kvmppc_gs_elem - serialized guest state buffer element + * @iden: Guest State ID + * @len: length of data + * @data: the guest state buffer element's value + */ +struct kvmppc_gs_elem { + __be16 iden; + __be16 len; + char data[]; +} __packed; + +/** + * struct kvmppc_gs_buff - a guest state buffer with metadata. + * @capacity: total length of the buffer + * @len: current length of the elements and header + * @guest_id: guest id associated with the buffer + * @vcpu_id: vcpu_id associated with the buffer + * @hdr: the serialised guest state buffer + */ +struct kvmppc_gs_buff { + size_t capacity; + size_t len; + unsigned long guest_id; + unsigned long vcpu_id; + struct kvmppc_gs_header *hdr; +}; + +/** + * struct kvmppc_gs_bitmap - a bitmap for element ids + * @bitmap: a bitmap large enough for all Guest State IDs + */ +struct kvmppc_gs_bitmap { + /* private: */ + DECLARE_BITMAP(bitmap, KVMPPC_GSE_IDEN_COUNT); +}; + +/** + * struct kvmppc_gs_parser - a map of element ids to locations in a buffer + * @iterator: bitmap used for iterating + * @gses: contains the pointers to elements + * + * A guest state parser is used for deserialising a guest state buffer. + * Given a buffer, it then allows looking up guest state elements using + * a guest state id. + */ +struct kvmppc_gs_parser { + /* private: */ + struct kvmppc_gs_bitmap iterator; + struct kvmppc_gs_elem *gses[KVMPPC_GSE_IDEN_COUNT]; +}; + +enum { + GSM_GUEST_WIDE = 0x1, + GSM_SEND = 0x2, + GSM_RECEIVE = 0x4, + GSM_GSB_OWNER = 0x8, +}; + +struct kvmppc_gs_msg; + +/** + * struct kvmppc_gs_msg_ops - guest state message behavior + * @get_size: maximum size required for the message data + * @fill_info: serializes to the guest state buffer format + * @refresh_info: dserializes from the guest state buffer format + */ +struct kvmppc_gs_msg_ops { + size_t (*get_size)(struct kvmppc_gs_msg *gsm); + int (*fill_info)(struct kvmppc_gs_buff *gsb, struct kvmppc_gs_msg *gsm); + int (*refresh_info)(struct kvmppc_gs_msg *gsm, + struct kvmppc_gs_buff *gsb); +}; + +/** + * struct kvmppc_gs_msg - a guest state message + * @bitmap: the guest state ids that should be included + * @ops: modify message behavior for reading and writing to buffers + * @flags: guest wide or thread wide + * @data: location where buffer data will be written to or from. + * + * A guest state message is allows flexibility in sending in receiving data + * in a guest state buffer format. + */ +struct kvmppc_gs_msg { + struct kvmppc_gs_bitmap bitmap; + struct kvmppc_gs_msg_ops *ops; + unsigned long flags; + void *data; +}; + +/************************************************************************** + * Guest State IDs + **************************************************************************/ + +u16 kvmppc_gsid_size(u16 iden); +unsigned long kvmppc_gsid_flags(u16 iden); +u64 kvmppc_gsid_mask(u16 iden); + +/************************************************************************** + * Guest State Buffers + **************************************************************************/ +struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id, + unsigned long vcpu_id, gfp_t flags); +void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb); +void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size); +int kvmppc_gsb_send(struct kvmppc_gs_buff *gsb, unsigned long flags); +int kvmppc_gsb_recv(struct kvmppc_gs_buff *gsb, unsigned long flags); + +/** + * kvmppc_gsb_header() - the header of a guest state buffer + * @gsb: guest state buffer + * + * Returns a pointer to the buffer header. + */ +static inline struct kvmppc_gs_header * +kvmppc_gsb_header(struct kvmppc_gs_buff *gsb) +{ + return gsb->hdr; +} + +/** + * kvmppc_gsb_data() - the elements of a guest state buffer + * @gsb: guest state buffer + * + * Returns a pointer to the first element of the buffer data. + */ +static inline struct kvmppc_gs_elem *kvmppc_gsb_data(struct kvmppc_gs_buff *gsb) +{ + return (struct kvmppc_gs_elem *)kvmppc_gsb_header(gsb)->data; +} + +/** + * kvmppc_gsb_len() - the current length of a guest state buffer + * @gsb: guest state buffer + * + * Returns the length including the header of a buffer. + */ +static inline size_t kvmppc_gsb_len(struct kvmppc_gs_buff *gsb) +{ + return gsb->len; +} + +/** + * kvmppc_gsb_capacity() - the capacity of a guest state buffer + * @gsb: guest state buffer + * + * Returns the capacity of a buffer. + */ +static inline size_t kvmppc_gsb_capacity(struct kvmppc_gs_buff *gsb) +{ + return gsb->capacity; +} + +/** + * kvmppc_gsb_paddress() - the physical address of buffer + * @gsb: guest state buffer + * + * Returns the physical address of the buffer. + */ +static inline u64 kvmppc_gsb_paddress(struct kvmppc_gs_buff *gsb) +{ + return __pa(kvmppc_gsb_header(gsb)); +} + +/** + * kvmppc_gsb_nelems() - the number of elements in a buffer + * @gsb: guest state buffer + * + * Returns the number of elements in a buffer + */ +static inline u32 kvmppc_gsb_nelems(struct kvmppc_gs_buff *gsb) +{ + return be32_to_cpu(kvmppc_gsb_header(gsb)->nelems); +} + +/** + * kvmppc_gsb_reset() - empty a guest state buffer + * @gsb: guest state buffer + * + * Reset the number of elements and length of buffer to empty. + */ +static inline void kvmppc_gsb_reset(struct kvmppc_gs_buff *gsb) +{ + kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(0); + gsb->len = sizeof(struct kvmppc_gs_header); +} + +/** + * kvmppc_gsb_data_len() - the length of a buffer excluding the header + * @gsb: guest state buffer + * + * Returns the length of a buffer excluding the header + */ +static inline size_t kvmppc_gsb_data_len(struct kvmppc_gs_buff *gsb) +{ + return gsb->len - sizeof(struct kvmppc_gs_header); +} + +/** + * kvmppc_gsb_data_cap() - the capacity of a buffer excluding the header + * @gsb: guest state buffer + * + * Returns the capacity of a buffer excluding the header + */ +static inline size_t kvmppc_gsb_data_cap(struct kvmppc_gs_buff *gsb) +{ + return gsb->capacity - sizeof(struct kvmppc_gs_header); +} + +/** + * kvmppc_gsb_for_each_elem - iterate over the elements in a buffer + * @i: loop counter + * @pos: set to current element + * @gsb: guest state buffer + * @rem: initialized to buffer capacity, holds bytes currently remaining in + * stream + */ +#define kvmppc_gsb_for_each_elem(i, pos, gsb, rem) \ + kvmppc_gse_for_each_elem(i, kvmppc_gsb_nelems(gsb), pos, \ + kvmppc_gsb_data(gsb), \ + kvmppc_gsb_data_cap(gsb), rem) + +/************************************************************************** + * Guest State Elements + **************************************************************************/ + +/** + * kvmppc_gse_iden() - guest state ID of element + * @gse: guest state element + * + * Return the guest state ID in host endianness. + */ +static inline u16 kvmppc_gse_iden(const struct kvmppc_gs_elem *gse) +{ + return be16_to_cpu(gse->iden); +} + +/** + * kvmppc_gse_len() - length of guest state element data + * @gse: guest state element + * + * Returns the length of guest state element data + */ +static inline u16 kvmppc_gse_len(const struct kvmppc_gs_elem *gse) +{ + return be16_to_cpu(gse->len); +} + +/** + * kvmppc_gse_total_len() - total length of guest state element + * @gse: guest state element + * + * Returns the length of the data plus the ID and size header. + */ +static inline u16 kvmppc_gse_total_len(const struct kvmppc_gs_elem *gse) +{ + return be16_to_cpu(gse->len) + sizeof(*gse); +} + +/** + * kvmppc_gse_total_size() - space needed for a given data length + * @size: data length + * + * Returns size plus the space needed for the ID and size header. + */ +static inline u16 kvmppc_gse_total_size(u16 size) +{ + return sizeof(struct kvmppc_gs_elem) + size; +} + +/** + * kvmppc_gse_data() - pointer to data of a guest state element + * @gse: guest state element + * + * Returns a pointer to the beginning of guest state element data. + */ +static inline void *kvmppc_gse_data(const struct kvmppc_gs_elem *gse) +{ + return (void *)gse->data; +} + +/** + * kvmppc_gse_ok() - checks space exists for guest state element + * @gse: guest state element + * @remaining: bytes of space remaining + * + * Returns true if the guest state element can fit in remaining space. + */ +static inline bool kvmppc_gse_ok(const struct kvmppc_gs_elem *gse, + int remaining) +{ + return remaining >= kvmppc_gse_total_len(gse); +} + +/** + * kvmppc_gse_next() - iterate to the next guest state element in a stream + * @gse: stream of guest state elements + * @remaining: length of the guest element stream + * + * Returns the next guest state element in a stream of elements. The length of + * the stream is updated in remaining. + */ +static inline struct kvmppc_gs_elem * +kvmppc_gse_next(const struct kvmppc_gs_elem *gse, int *remaining) +{ + int len = sizeof(*gse) + kvmppc_gse_len(gse); + + *remaining -= len; + return (struct kvmppc_gs_elem *)(gse->data + kvmppc_gse_len(gse)); +} + +/** + * kvmppc_gse_for_each_elem - iterate over a stream of guest state elements + * @i: loop counter + * @max: number of elements + * @pos: set to current element + * @head: head of elements + * @len: length of the stream + * @rem: initialized to len, holds bytes currently remaining elements + */ +#define kvmppc_gse_for_each_elem(i, max, pos, head, len, rem) \ + for (i = 0, pos = head, rem = len; kvmppc_gse_ok(pos, rem) && i < max; \ + pos = kvmppc_gse_next(pos, &(rem)), i++) + +int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, + const void *data); +int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb); + +/** + * kvmppc_gse_put_be32() - add a be32 guest state element to a buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: big endian value + */ +static inline int kvmppc_gse_put_be32(struct kvmppc_gs_buff *gsb, u16 iden, + __be32 val) +{ + __be32 tmp; + + tmp = val; + return __kvmppc_gse_put(gsb, iden, sizeof(__be32), &tmp); +} + +/** + * kvmppc_gse_put_u32() - add a host endian 32bit int guest state element to a + * buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: host endian value + */ +static inline int kvmppc_gse_put_u32(struct kvmppc_gs_buff *gsb, u16 iden, + u32 val) +{ + __be32 tmp; + + val &= kvmppc_gsid_mask(iden); + tmp = cpu_to_be32(val); + return kvmppc_gse_put_be32(gsb, iden, tmp); +} + +/** + * kvmppc_gse_put_be64() - add a be64 guest state element to a buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: big endian value + */ +static inline int kvmppc_gse_put_be64(struct kvmppc_gs_buff *gsb, u16 iden, + __be64 val) +{ + __be64 tmp; + + tmp = val; + return __kvmppc_gse_put(gsb, iden, sizeof(__be64), &tmp); +} + +/** + * kvmppc_gse_put_u64() - add a host endian 64bit guest state element to a + * buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: host endian value + */ +static inline int kvmppc_gse_put_u64(struct kvmppc_gs_buff *gsb, u16 iden, + u64 val) +{ + __be64 tmp; + + val &= kvmppc_gsid_mask(iden); + tmp = cpu_to_be64(val); + return kvmppc_gse_put_be64(gsb, iden, tmp); +} + +/** + * __kvmppc_gse_put_reg() - add a register type guest state element to a buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: host endian value + * + * Adds a register type guest state element. Uses the guest state ID for + * determining the length of the guest element. If the guest state ID has + * bits that can not be set they will be cleared. + */ +static inline int __kvmppc_gse_put_reg(struct kvmppc_gs_buff *gsb, u16 iden, + u64 val) +{ + val &= kvmppc_gsid_mask(iden); + if (kvmppc_gsid_size(iden) == sizeof(u64)) + return kvmppc_gse_put_u64(gsb, iden, val); + + if (kvmppc_gsid_size(iden) == sizeof(u32)) { + u32 tmp; + + tmp = (u32)val; + if (tmp != val) + return -EINVAL; + + return kvmppc_gse_put_u32(gsb, iden, tmp); + } + return -EINVAL; +} + +/** + * kvmppc_gse_put_vector128() - add a vector guest state element to a buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: 16 byte vector value + */ +static inline int kvmppc_gse_put_vector128(struct kvmppc_gs_buff *gsb, u16 iden, + vector128 *val) +{ + __be64 tmp[2] = { 0 }; + union { + __vector128 v; + u64 dw[2]; + } u; + + u.v = *val; + tmp[0] = cpu_to_be64(u.dw[TS_FPROFFSET]); +#ifdef CONFIG_VSX + tmp[1] = cpu_to_be64(u.dw[TS_VSRLOWOFFSET]); +#endif + return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp); +} + +/** + * kvmppc_gse_put_part_table() - add a partition table guest state element to a + * buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: partition table value + */ +static inline int kvmppc_gse_put_part_table(struct kvmppc_gs_buff *gsb, + u16 iden, + struct kvmppc_gs_part_table val) +{ + __be64 tmp[3]; + + tmp[0] = cpu_to_be64(val.address); + tmp[1] = cpu_to_be64(val.ea_bits); + tmp[2] = cpu_to_be64(val.gpd_size); + return __kvmppc_gse_put(gsb, KVMPPC_GSID_PARTITION_TABLE, sizeof(tmp), + &tmp); +} + +/** + * kvmppc_gse_put_proc_table() - add a process table guest state element to a + * buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: process table value + */ +static inline int kvmppc_gse_put_proc_table(struct kvmppc_gs_buff *gsb, + u16 iden, + struct kvmppc_gs_proc_table val) +{ + __be64 tmp[2]; + + tmp[0] = cpu_to_be64(val.address); + tmp[1] = cpu_to_be64(val.gpd_size); + return __kvmppc_gse_put(gsb, KVMPPC_GSID_PROCESS_TABLE, sizeof(tmp), + &tmp); +} + +/** + * kvmppc_gse_put_buff_info() - adds a GSB description guest state element to a + * buffer + * @gsb: guest state buffer to add element to + * @iden: guest state ID + * @val: guest state buffer description value + */ +static inline int kvmppc_gse_put_buff_info(struct kvmppc_gs_buff *gsb, u16 iden, + struct kvmppc_gs_buff_info val) +{ + __be64 tmp[2]; + + tmp[0] = cpu_to_be64(val.address); + tmp[1] = cpu_to_be64(val.size); + return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp); +} + +int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, + const void *data); + +/** + * kvmppc_gse_get_be32() - return the data of a be32 element + * @gse: guest state element + */ +static inline __be32 kvmppc_gse_get_be32(const struct kvmppc_gs_elem *gse) +{ + if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be32))) + return 0; + return *(__be32 *)kvmppc_gse_data(gse); +} + +/** + * kvmppc_gse_get_u32() - return the data of a be32 element in host endianness + * @gse: guest state element + */ +static inline u32 kvmppc_gse_get_u32(const struct kvmppc_gs_elem *gse) +{ + return be32_to_cpu(kvmppc_gse_get_be32(gse)); +} + +/** + * kvmppc_gse_get_be64() - return the data of a be64 element + * @gse: guest state element + */ +static inline __be64 kvmppc_gse_get_be64(const struct kvmppc_gs_elem *gse) +{ + if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be64))) + return 0; + return *(__be64 *)kvmppc_gse_data(gse); +} + +/** + * kvmppc_gse_get_u64() - return the data of a be64 element in host endianness + * @gse: guest state element + */ +static inline u64 kvmppc_gse_get_u64(const struct kvmppc_gs_elem *gse) +{ + return be64_to_cpu(kvmppc_gse_get_be64(gse)); +} + +/** + * kvmppc_gse_get_vector128() - return the data of a vector element + * @gse: guest state element + */ +static inline void kvmppc_gse_get_vector128(const struct kvmppc_gs_elem *gse, + vector128 *v) +{ + union { + __vector128 v; + u64 dw[2]; + } u = { 0 }; + __be64 *src; + + if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__vector128))) + *v = u.v; + + src = (__be64 *)kvmppc_gse_data(gse); + u.dw[TS_FPROFFSET] = be64_to_cpu(src[0]); +#ifdef CONFIG_VSX + u.dw[TS_VSRLOWOFFSET] = be64_to_cpu(src[1]); +#endif + *v = u.v; +} + +/************************************************************************** + * Guest State Bitmap + **************************************************************************/ + +bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden); +void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden); +void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden); +u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev); + +/** + * kvmppc_gsbm_zero - zero the entire bitmap + * @gsbm: guest state buffer bitmap + */ +static inline void kvmppc_gsbm_zero(struct kvmppc_gs_bitmap *gsbm) +{ + bitmap_zero(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT); +} + +/** + * kvmppc_gsbm_fill - fill the entire bitmap + * @gsbm: guest state buffer bitmap + */ +static inline void kvmppc_gsbm_fill(struct kvmppc_gs_bitmap *gsbm) +{ + bitmap_fill(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT); + clear_bit(0, gsbm->bitmap); +} + +/** + * kvmppc_gsbm_for_each - iterate the present guest state IDs + * @gsbm: guest state buffer bitmap + * @iden: current guest state ID + */ +#define kvmppc_gsbm_for_each(gsbm, iden) \ + for (iden = kvmppc_gsbm_next(gsbm, 0); iden != 0; \ + iden = kvmppc_gsbm_next(gsbm, iden)) + +/************************************************************************** + * Guest State Parser + **************************************************************************/ + +void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden, + struct kvmppc_gs_elem *gse); +struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp, + u16 iden); + +/** + * kvmppc_gsp_for_each - iterate the + * pairs + * @gsp: guest state buffer bitmap + * @iden: current guest state ID + * @gse: guest state element + */ +#define kvmppc_gsp_for_each(gsp, iden, gse) \ + for (iden = kvmppc_gsbm_next(&(gsp)->iterator, 0), \ + gse = kvmppc_gsp_lookup((gsp), iden); \ + iden != 0; iden = kvmppc_gsbm_next(&(gsp)->iterator, iden), \ + gse = kvmppc_gsp_lookup((gsp), iden)) + +/************************************************************************** + * Guest State Message + **************************************************************************/ + +/** + * kvmppc_gsm_for_each - iterate the guest state IDs included in a guest state + * message + * @gsp: guest state buffer bitmap + * @iden: current guest state ID + * @gse: guest state element + */ +#define kvmppc_gsm_for_each(gsm, iden) \ + for (iden = kvmppc_gsbm_next(&gsm->bitmap, 0); iden != 0; \ + iden = kvmppc_gsbm_next(&gsm->bitmap, iden)) + +int kvmppc_gsm_init(struct kvmppc_gs_msg *mgs, struct kvmppc_gs_msg_ops *ops, + void *data, unsigned long flags); + +struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data, + unsigned long flags, gfp_t gfp_flags); +void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm); +size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm); +int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb); +int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm, + struct kvmppc_gs_buff *gsb); + +/** + * kvmppc_gsm_include - indicate a guest state ID should be included when + * serializing + * @gsm: guest state message + * @iden: guest state ID + */ +static inline void kvmppc_gsm_include(struct kvmppc_gs_msg *gsm, u16 iden) +{ + kvmppc_gsbm_set(&gsm->bitmap, iden); +} + +/** + * kvmppc_gsm_includes - check if a guest state ID will be included when + * serializing + * @gsm: guest state message + * @iden: guest state ID + */ +static inline bool kvmppc_gsm_includes(struct kvmppc_gs_msg *gsm, u16 iden) +{ + return kvmppc_gsbm_test(&gsm->bitmap, iden); +} + +/** + * kvmppc_gsm_includes - indicate all guest state IDs should be included when + * serializing + * @gsm: guest state message + * @iden: guest state ID + */ +static inline void kvmppc_gsm_include_all(struct kvmppc_gs_msg *gsm) +{ + kvmppc_gsbm_fill(&gsm->bitmap); +} + +/** + * kvmppc_gsm_include - clear the guest state IDs that should be included when + * serializing + * @gsm: guest state message + */ +static inline void kvmppc_gsm_reset(struct kvmppc_gs_msg *gsm) +{ + kvmppc_gsbm_zero(&gsm->bitmap); +} + +/** + * kvmppc_gsb_receive_data - flexibly update values from a guest state buffer + * @gsb: guest state buffer + * @gsm: guest state message + * + * Requests updated values for the guest state values included in the guest + * state message. The guest state message will then deserialize the guest state + * buffer. + */ +static inline int kvmppc_gsb_receive_data(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm) +{ + int rc; + + kvmppc_gsb_reset(gsb); + rc = kvmppc_gsm_fill_info(gsm, gsb); + if (rc < 0) + return rc; + + rc = kvmppc_gsb_recv(gsb, gsm->flags); + if (rc < 0) + return rc; + + rc = kvmppc_gsm_refresh_info(gsm, gsb); + if (rc < 0) + return rc; + return 0; +} + +/** + * kvmppc_gsb_recv - receive a single guest state ID + * @gsb: guest state buffer + * @gsm: guest state message + * @iden: guest state identity + */ +static inline int kvmppc_gsb_receive_datum(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm, u16 iden) +{ + int rc; + + kvmppc_gsm_include(gsm, iden); + rc = kvmppc_gsb_receive_data(gsb, gsm); + if (rc < 0) + return rc; + kvmppc_gsm_reset(gsm); + return 0; +} + +/** + * kvmppc_gsb_send_data - flexibly send values from a guest state buffer + * @gsb: guest state buffer + * @gsm: guest state message + * + * Sends the guest state values included in the guest state message. + */ +static inline int kvmppc_gsb_send_data(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm) +{ + int rc; + + kvmppc_gsb_reset(gsb); + rc = kvmppc_gsm_fill_info(gsm, gsb); + if (rc < 0) + return rc; + rc = kvmppc_gsb_send(gsb, gsm->flags); + + return rc; +} + +/** + * kvmppc_gsb_recv - send a single guest state ID + * @gsb: guest state buffer + * @gsm: guest state message + * @iden: guest state identity + */ +static inline int kvmppc_gsb_send_datum(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm, u16 iden) +{ + int rc; + + kvmppc_gsm_include(gsm, iden); + rc = kvmppc_gsb_send_data(gsb, gsm); + if (rc < 0) + return rc; + kvmppc_gsm_reset(gsm); + return 0; +} + +#endif /* _ASM_POWERPC_GUEST_STATE_BUFFER_H */ diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index c099780385dd..ddb99e982917 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -100,6 +100,18 @@ #define H_COP_HW -74 #define H_STATE -75 #define H_IN_USE -77 + +#define H_INVALID_ELEMENT_ID -79 +#define H_INVALID_ELEMENT_SIZE -80 +#define H_INVALID_ELEMENT_VALUE -81 +#define H_INPUT_BUFFER_NOT_DEFINED -82 +#define H_INPUT_BUFFER_TOO_SMALL -83 +#define H_OUTPUT_BUFFER_NOT_DEFINED -84 +#define H_OUTPUT_BUFFER_TOO_SMALL -85 +#define H_PARTITION_PAGE_TABLE_NOT_DEFINED -86 +#define H_GUEST_VCPU_STATE_NOT_HV_OWNED -87 + + #define H_UNSUPPORTED_FLAG_START -256 #define H_UNSUPPORTED_FLAG_END -511 #define H_MULTI_THREADS_ACTIVE -9005 @@ -381,6 +393,15 @@ #define H_ENTER_NESTED 0xF804 #define H_TLB_INVALIDATE 0xF808 #define H_COPY_TOFROM_GUEST 0xF80C +#define H_GUEST_GET_CAPABILITIES 0x460 +#define H_GUEST_SET_CAPABILITIES 0x464 +#define H_GUEST_CREATE 0x470 +#define H_GUEST_CREATE_VCPU 0x474 +#define H_GUEST_GET_STATE 0x478 +#define H_GUEST_SET_STATE 0x47C +#define H_GUEST_RUN_VCPU 0x480 +#define H_GUEST_COPY_MEMORY 0x484 +#define H_GUEST_DELETE 0x488 /* Flags for H_SVM_PAGE_IN */ #define H_PAGE_IN_SHARED 0x1 @@ -467,6 +488,15 @@ #define H_RPTI_PAGE_1G 0x08 #define H_RPTI_PAGE_ALL (-1UL) +/* Flags for H_GUEST_{S,G}_STATE */ +#define H_GUEST_FLAGS_WIDE (1UL<<(63-0)) + +/* Flag values used for H_{S,G}SET_GUEST_CAPABILITIES */ +#define H_GUEST_CAP_COPY_MEM (1UL<<(63-0)) +#define H_GUEST_CAP_POWER9 (1UL<<(63-1)) +#define H_GUEST_CAP_POWER10 (1UL<<(63-2)) +#define H_GUEST_CAP_BITMAP2 (1UL<<(63-63)) + #ifndef __ASSEMBLY__ #include diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h index 699a88584ae1..a656635df386 100644 --- a/arch/powerpc/include/asm/imc-pmu.h +++ b/arch/powerpc/include/asm/imc-pmu.h @@ -74,14 +74,14 @@ struct imc_events { * The following is the data structure to hold trace imc data. */ struct trace_imc_data { - u64 tb1; - u64 ip; - u64 val; - u64 cpmc1; - u64 cpmc2; - u64 cpmc3; - u64 cpmc4; - u64 tb2; + __be64 tb1; + __be64 ip; + __be64 val; + __be64 cpmc1; + __be64 cpmc2; + __be64 cpmc3; + __be64 cpmc4; + __be64 tb2; }; /* Event attribute array index */ diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index 0732b743e099..5220274a6277 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h @@ -950,7 +950,7 @@ extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size, * almost all conceivable cases a device driver should not be using * this function */ -static inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(const volatile void * address) { WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && !virt_addr_valid(address)); diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index a1ddba01e7d1..e1b43aa12175 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h @@ -99,10 +99,14 @@ void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_co void kexec_copy_flush(struct kimage *image); -#if defined(CONFIG_CRASH_DUMP) && defined(CONFIG_PPC_RTAS) +#if defined(CONFIG_CRASH_DUMP) +bool is_kdump_kernel(void); +#define is_kdump_kernel is_kdump_kernel +#if defined(CONFIG_PPC_RTAS) void crash_free_reserved_phys_range(unsigned long begin, unsigned long end); #define crash_free_reserved_phys_range crash_free_reserved_phys_range -#endif +#endif /* CONFIG_PPC_RTAS */ +#endif /* CONFIG_CRASH_DUMP */ #ifdef CONFIG_KEXEC_FILE extern const struct kexec_file_ops kexec_elf64_ops; diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index bbf5e2c5fe09..4f527d09c92b 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -12,6 +12,7 @@ #include #include #include +#include struct kvmppc_bat { u64 raw; @@ -191,14 +192,14 @@ extern int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr, extern int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *gpte, bool data, bool iswrite); extern void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr, - unsigned int pshift, unsigned int lpid); + unsigned int pshift, u64 lpid); extern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, unsigned int shift, const struct kvm_memory_slot *memslot, - unsigned int lpid); + u64 lpid); extern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested, bool writing, unsigned long gpa, - unsigned int lpid); + u64 lpid); extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, unsigned long gpa, struct kvm_memory_slot *memslot, @@ -207,7 +208,7 @@ extern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, extern int kvmppc_init_vm_radix(struct kvm *kvm); extern void kvmppc_free_radix(struct kvm *kvm); extern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, - unsigned int lpid); + u64 lpid); extern int kvmppc_radix_init(void); extern void kvmppc_radix_exit(void); extern void kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, @@ -295,12 +296,13 @@ static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {} static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {} #endif +extern unsigned long nested_capabilities; long kvmhv_nested_init(void); void kvmhv_nested_exit(void); void kvmhv_vm_nested_init(struct kvm *kvm); long kvmhv_set_partition_table(struct kvm_vcpu *vcpu); long kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu); -void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1); +void kvmhv_set_ptbl_entry(u64 lpid, u64 dw0, u64 dw1); void kvmhv_release_all_nested(struct kvm *kvm); long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu); long kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu); @@ -316,6 +318,69 @@ long int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu); void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac); + +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE + +extern struct static_key_false __kvmhv_is_nestedv2; + +static inline bool kvmhv_is_nestedv2(void) +{ + return static_branch_unlikely(&__kvmhv_is_nestedv2); +} + +static inline bool kvmhv_is_nestedv1(void) +{ + return !static_branch_likely(&__kvmhv_is_nestedv2); +} + +#else + +static inline bool kvmhv_is_nestedv2(void) +{ + return false; +} + +static inline bool kvmhv_is_nestedv1(void) +{ + return false; +} + +#endif + +int __kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs); +int __kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs); +int __kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden); +int __kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden); + +static inline int kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, + struct pt_regs *regs) +{ + if (kvmhv_is_nestedv2()) + return __kvmhv_nestedv2_reload_ptregs(vcpu, regs); + return 0; +} +static inline int kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu, + struct pt_regs *regs) +{ + if (kvmhv_is_nestedv2()) + return __kvmhv_nestedv2_mark_dirty_ptregs(vcpu, regs); + return 0; +} + +static inline int kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden) +{ + if (kvmhv_is_nestedv2()) + return __kvmhv_nestedv2_mark_dirty(vcpu, iden); + return 0; +} + +static inline int kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden) +{ + if (kvmhv_is_nestedv2()) + return __kvmhv_nestedv2_cached_reload(vcpu, iden); + return 0; +} + extern int kvm_irq_bypass; static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) @@ -335,60 +400,72 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) { vcpu->arch.regs.gpr[num] = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_GPR(num)); } static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) { + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_GPR(num)) < 0); return vcpu->arch.regs.gpr[num]; } static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) { vcpu->arch.regs.ccr = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CR); } static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) { + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_CR) < 0); return vcpu->arch.regs.ccr; } static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) { vcpu->arch.regs.xer = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_XER); } static inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu) { + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_XER) < 0); return vcpu->arch.regs.xer; } static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) { vcpu->arch.regs.ctr = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CTR); } static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) { + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_CTR) < 0); return vcpu->arch.regs.ctr; } static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) { vcpu->arch.regs.link = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LR); } static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) { + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_LR) < 0); return vcpu->arch.regs.link; } static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) { vcpu->arch.regs.nip = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_NIA); } static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) { + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_NIA) < 0); return vcpu->arch.regs.nip; } @@ -403,10 +480,141 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) return vcpu->arch.fault_dar; } +static inline u64 kvmppc_get_fpr(struct kvm_vcpu *vcpu, int i) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSRS(i)) < 0); + return vcpu->arch.fp.fpr[i][TS_FPROFFSET]; +} + +static inline void kvmppc_set_fpr(struct kvm_vcpu *vcpu, int i, u64 val) +{ + vcpu->arch.fp.fpr[i][TS_FPROFFSET] = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSRS(i)); +} + +static inline u64 kvmppc_get_fpscr(struct kvm_vcpu *vcpu) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_FPSCR) < 0); + return vcpu->arch.fp.fpscr; +} + +static inline void kvmppc_set_fpscr(struct kvm_vcpu *vcpu, u64 val) +{ + vcpu->arch.fp.fpscr = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_FPSCR); +} + + +static inline u64 kvmppc_get_vsx_fpr(struct kvm_vcpu *vcpu, int i, int j) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSRS(i)) < 0); + return vcpu->arch.fp.fpr[i][j]; +} + +static inline void kvmppc_set_vsx_fpr(struct kvm_vcpu *vcpu, int i, int j, + u64 val) +{ + vcpu->arch.fp.fpr[i][j] = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSRS(i)); +} + +#ifdef CONFIG_ALTIVEC +static inline void kvmppc_get_vsx_vr(struct kvm_vcpu *vcpu, int i, vector128 *v) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSRS(32 + i)) < 0); + *v = vcpu->arch.vr.vr[i]; +} + +static inline void kvmppc_set_vsx_vr(struct kvm_vcpu *vcpu, int i, + vector128 *val) +{ + vcpu->arch.vr.vr[i] = *val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSRS(32 + i)); +} + +static inline u32 kvmppc_get_vscr(struct kvm_vcpu *vcpu) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_VSCR) < 0); + return vcpu->arch.vr.vscr.u[3]; +} + +static inline void kvmppc_set_vscr(struct kvm_vcpu *vcpu, u32 val) +{ + vcpu->arch.vr.vscr.u[3] = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_VSCR); +} +#endif + +#define KVMPPC_BOOK3S_VCPU_ACCESSOR_SET(reg, size, iden) \ +static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \ +{ \ + \ + vcpu->arch.reg = val; \ + kvmhv_nestedv2_mark_dirty(vcpu, iden); \ +} + +#define KVMPPC_BOOK3S_VCPU_ACCESSOR_GET(reg, size, iden) \ +static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ +{ \ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden) < 0); \ + return vcpu->arch.reg; \ +} + +#define KVMPPC_BOOK3S_VCPU_ACCESSOR(reg, size, iden) \ + KVMPPC_BOOK3S_VCPU_ACCESSOR_SET(reg, size, iden) \ + KVMPPC_BOOK3S_VCPU_ACCESSOR_GET(reg, size, iden) \ + +KVMPPC_BOOK3S_VCPU_ACCESSOR(pid, 32, KVMPPC_GSID_PIDR) +KVMPPC_BOOK3S_VCPU_ACCESSOR(tar, 64, KVMPPC_GSID_TAR) +KVMPPC_BOOK3S_VCPU_ACCESSOR(ebbhr, 64, KVMPPC_GSID_EBBHR) +KVMPPC_BOOK3S_VCPU_ACCESSOR(ebbrr, 64, KVMPPC_GSID_EBBRR) +KVMPPC_BOOK3S_VCPU_ACCESSOR(bescr, 64, KVMPPC_GSID_BESCR) +KVMPPC_BOOK3S_VCPU_ACCESSOR(ic, 64, KVMPPC_GSID_IC) +KVMPPC_BOOK3S_VCPU_ACCESSOR(vrsave, 64, KVMPPC_GSID_VRSAVE) + + +#define KVMPPC_BOOK3S_VCORE_ACCESSOR_SET(reg, size, iden) \ +static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \ +{ \ + vcpu->arch.vcore->reg = val; \ + kvmhv_nestedv2_mark_dirty(vcpu, iden); \ +} + +#define KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(reg, size, iden) \ +static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ +{ \ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden) < 0); \ + return vcpu->arch.vcore->reg; \ +} + +#define KVMPPC_BOOK3S_VCORE_ACCESSOR(reg, size, iden) \ + KVMPPC_BOOK3S_VCORE_ACCESSOR_SET(reg, size, iden) \ + KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(reg, size, iden) \ + + +KVMPPC_BOOK3S_VCORE_ACCESSOR(vtb, 64, KVMPPC_GSID_VTB) +KVMPPC_BOOK3S_VCORE_ACCESSOR(tb_offset, 64, KVMPPC_GSID_TB_OFFSET) +KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(arch_compat, 32, KVMPPC_GSID_LOGICAL_PVR) +KVMPPC_BOOK3S_VCORE_ACCESSOR_GET(lpcr, 64, KVMPPC_GSID_LPCR) + +static inline u64 kvmppc_get_dec_expires(struct kvm_vcpu *vcpu) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_TB_OFFSET) < 0); + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_DEC_EXPIRY_TB) < 0); + return vcpu->arch.dec_expires; +} + +static inline void kvmppc_set_dec_expires(struct kvm_vcpu *vcpu, u64 val) +{ + vcpu->arch.dec_expires = val; + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_TB_OFFSET) < 0); + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_DEC_EXPIRY_TB); +} + /* Expiry time of vcpu DEC relative to host TB */ static inline u64 kvmppc_dec_expires_host_tb(struct kvm_vcpu *vcpu) { - return vcpu->arch.dec_expires - vcpu->arch.vcore->tb_offset; + return kvmppc_get_dec_expires(vcpu) - kvmppc_get_tb_offset(vcpu); } static inline bool is_kvmppc_resume_guest(int r) diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index d49065af08e9..2477021bff54 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -624,7 +624,7 @@ static inline void copy_to_checkpoint(struct kvm_vcpu *vcpu) extern int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte, unsigned long gpa, unsigned int level, - unsigned long mmu_seq, unsigned int lpid, + unsigned long mmu_seq, u64 lpid, unsigned long *rmapp, struct rmap_nested **n_rmap); extern void kvmhv_insert_nest_rmap(struct kvm *kvm, unsigned long *rmapp, struct rmap_nested **n_rmap); @@ -677,6 +677,12 @@ static inline pte_t *find_kvm_host_pte(struct kvm *kvm, unsigned long mmu_seq, extern pte_t *find_kvm_nested_guest_pte(struct kvm *kvm, unsigned long lpid, unsigned long ea, unsigned *hshift); +int kvmhv_nestedv2_vcpu_create(struct kvm_vcpu *vcpu, struct kvmhv_nestedv2_io *io); +void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu, struct kvmhv_nestedv2_io *io); +int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit); +int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1); +int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu); + #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ #endif /* __ASM_KVM_BOOK3S_64_H__ */ diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h index 0c3401b2e19e..7c3291aa8922 100644 --- a/arch/powerpc/include/asm/kvm_booke.h +++ b/arch/powerpc/include/asm/kvm_booke.h @@ -89,6 +89,16 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) return vcpu->arch.regs.nip; } +static inline void kvmppc_set_fpr(struct kvm_vcpu *vcpu, int i, u64 val) +{ + vcpu->arch.fp.fpr[i][TS_FPROFFSET] = val; +} + +static inline u64 kvmppc_get_fpr(struct kvm_vcpu *vcpu, int i) +{ + return vcpu->arch.fp.fpr[i][TS_FPROFFSET]; +} + #ifdef CONFIG_BOOKE static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) { diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 14ee0dece853..8799b37be295 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -25,6 +25,7 @@ #include #include #include +#include #define __KVM_HAVE_ARCH_VCPU_DEBUGFS @@ -276,7 +277,7 @@ struct kvm_resize_hpt; #define KVMPPC_SECURE_INIT_ABORT 0x4 /* H_SVM_INIT_ABORT issued */ struct kvm_arch { - unsigned int lpid; + u64 lpid; unsigned int smt_mode; /* # vcpus per virtual core */ unsigned int emul_smt_mode; /* emualted SMT mode, on P9 */ #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE @@ -509,6 +510,23 @@ union xive_tma_w01 { __be64 w01; }; + /* Nestedv2 H_GUEST_RUN_VCPU configuration */ +struct kvmhv_nestedv2_config { + struct kvmppc_gs_buff_info vcpu_run_output_cfg; + struct kvmppc_gs_buff_info vcpu_run_input_cfg; + u64 vcpu_run_output_size; +}; + + /* Nestedv2 L1<->L0 communication state */ +struct kvmhv_nestedv2_io { + struct kvmhv_nestedv2_config cfg; + struct kvmppc_gs_buff *vcpu_run_output; + struct kvmppc_gs_buff *vcpu_run_input; + struct kvmppc_gs_msg *vcpu_message; + struct kvmppc_gs_msg *vcore_message; + struct kvmppc_gs_bitmap valids; +}; + struct kvm_vcpu_arch { ulong host_stack; u32 host_pid; @@ -829,6 +847,8 @@ struct kvm_vcpu_arch { u64 nested_hfscr; /* HFSCR that the L1 requested for the nested guest */ u32 nested_vcpu_id; gpa_t nested_io_gpr; + /* For nested APIv2 guests*/ + struct kvmhv_nestedv2_io nestedv2_io; #endif #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index b4da8514af43..3281215097cc 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -615,6 +615,42 @@ static inline bool kvmhv_on_pseries(void) { return false; } + +#endif + +#ifndef CONFIG_PPC_BOOK3S + +static inline bool kvmhv_is_nestedv2(void) +{ + return false; +} + +static inline bool kvmhv_is_nestedv1(void) +{ + return false; +} + +static inline int kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, + struct pt_regs *regs) +{ + return 0; +} +static inline int kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu, + struct pt_regs *regs) +{ + return 0; +} + +static inline int kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden) +{ + return 0; +} + +static inline int kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden) +{ + return 0; +} + #endif #ifdef CONFIG_KVM_XICS @@ -927,79 +963,85 @@ static inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu) #endif } -#define SPRNG_WRAPPER_GET(reg, bookehv_spr) \ +#define KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_GET(reg, bookehv_spr) \ static inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ { \ return mfspr(bookehv_spr); \ } \ -#define SPRNG_WRAPPER_SET(reg, bookehv_spr) \ +#define KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_SET(reg, bookehv_spr) \ static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val) \ { \ mtspr(bookehv_spr, val); \ } \ -#define SHARED_WRAPPER_GET(reg, size) \ +#define KVMPPC_VCPU_SHARED_REGS_ACCESSOR_GET(reg, size, iden) \ static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ { \ + if (iden) \ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden) < 0); \ if (kvmppc_shared_big_endian(vcpu)) \ - return be##size##_to_cpu(vcpu->arch.shared->reg); \ + return be##size##_to_cpu((__be##size __force)vcpu->arch.shared->reg); \ else \ - return le##size##_to_cpu(vcpu->arch.shared->reg); \ + return le##size##_to_cpu((__le##size __force)vcpu->arch.shared->reg); \ } \ -#define SHARED_WRAPPER_SET(reg, size) \ +#define KVMPPC_VCPU_SHARED_REGS_ACCESSOR_SET(reg, size, iden) \ static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \ { \ if (kvmppc_shared_big_endian(vcpu)) \ - vcpu->arch.shared->reg = cpu_to_be##size(val); \ + vcpu->arch.shared->reg = (u##size __force)cpu_to_be##size(val); \ else \ - vcpu->arch.shared->reg = cpu_to_le##size(val); \ + vcpu->arch.shared->reg = (u##size __force)cpu_to_le##size(val); \ + \ + if (iden) \ + kvmhv_nestedv2_mark_dirty(vcpu, iden); \ } \ -#define SHARED_WRAPPER(reg, size) \ - SHARED_WRAPPER_GET(reg, size) \ - SHARED_WRAPPER_SET(reg, size) \ +#define KVMPPC_VCPU_SHARED_REGS_ACCESSOR(reg, size, iden) \ + KVMPPC_VCPU_SHARED_REGS_ACCESSOR_GET(reg, size, iden) \ + KVMPPC_VCPU_SHARED_REGS_ACCESSOR_SET(reg, size, iden) \ -#define SPRNG_WRAPPER(reg, bookehv_spr) \ - SPRNG_WRAPPER_GET(reg, bookehv_spr) \ - SPRNG_WRAPPER_SET(reg, bookehv_spr) \ +#define KVMPPC_BOOKE_HV_SPRNG_ACCESSOR(reg, bookehv_spr) \ + KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_GET(reg, bookehv_spr) \ + KVMPPC_BOOKE_HV_SPRNG_ACCESSOR_SET(reg, bookehv_spr) \ #ifdef CONFIG_KVM_BOOKE_HV -#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \ - SPRNG_WRAPPER(reg, bookehv_spr) \ +#define KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(reg, size, bookehv_spr, iden) \ + KVMPPC_BOOKE_HV_SPRNG_ACCESSOR(reg, bookehv_spr) \ #else -#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \ - SHARED_WRAPPER(reg, size) \ +#define KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(reg, size, bookehv_spr, iden) \ + KVMPPC_VCPU_SHARED_REGS_ACCESSOR(reg, size, iden) \ #endif -SHARED_WRAPPER(critical, 64) -SHARED_SPRNG_WRAPPER(sprg0, 64, SPRN_GSPRG0) -SHARED_SPRNG_WRAPPER(sprg1, 64, SPRN_GSPRG1) -SHARED_SPRNG_WRAPPER(sprg2, 64, SPRN_GSPRG2) -SHARED_SPRNG_WRAPPER(sprg3, 64, SPRN_GSPRG3) -SHARED_SPRNG_WRAPPER(srr0, 64, SPRN_GSRR0) -SHARED_SPRNG_WRAPPER(srr1, 64, SPRN_GSRR1) -SHARED_SPRNG_WRAPPER(dar, 64, SPRN_GDEAR) -SHARED_SPRNG_WRAPPER(esr, 64, SPRN_GESR) -SHARED_WRAPPER_GET(msr, 64) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(critical, 64, 0) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg0, 64, SPRN_GSPRG0, KVMPPC_GSID_SPRG0) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg1, 64, SPRN_GSPRG1, KVMPPC_GSID_SPRG1) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg2, 64, SPRN_GSPRG2, KVMPPC_GSID_SPRG2) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(sprg3, 64, SPRN_GSPRG3, KVMPPC_GSID_SPRG3) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(srr0, 64, SPRN_GSRR0, KVMPPC_GSID_SRR0) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(srr1, 64, SPRN_GSRR1, KVMPPC_GSID_SRR1) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(dar, 64, SPRN_GDEAR, KVMPPC_GSID_DAR) +KVMPPC_BOOKE_HV_SPRNG_OR_VCPU_SHARED_REGS_ACCESSOR(esr, 64, SPRN_GESR, 0) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR_GET(msr, 64, KVMPPC_GSID_MSR) static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val) { if (kvmppc_shared_big_endian(vcpu)) vcpu->arch.shared->msr = cpu_to_be64(val); else vcpu->arch.shared->msr = cpu_to_le64(val); + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_MSR); } -SHARED_WRAPPER(dsisr, 32) -SHARED_WRAPPER(int_pending, 32) -SHARED_WRAPPER(sprg4, 64) -SHARED_WRAPPER(sprg5, 64) -SHARED_WRAPPER(sprg6, 64) -SHARED_WRAPPER(sprg7, 64) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(dsisr, 32, KVMPPC_GSID_DSISR) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(int_pending, 32, 0) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg4, 64, 0) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg5, 64, 0) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg6, 64, 0) +KVMPPC_VCPU_SHARED_REGS_ACCESSOR(sprg7, 64, 0) static inline u32 kvmppc_get_sr(struct kvm_vcpu *vcpu, int nr) { diff --git a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h index 0e93a4728c9e..141d82e249a8 100644 --- a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h @@ -188,7 +188,6 @@ typedef struct { } mm_context_t; #define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000) -#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE)) /* Page size definitions, common between 32 and 64-bit * diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index f99c53a5f184..9164a9e41b02 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h @@ -9,10 +9,6 @@ #include #include /* For sub-arch specific PPC_PIN_SIZE */ -#ifdef CONFIG_44x -extern int icache_44x_need_flush; -#endif - #endif /* __ASSEMBLY__ */ #define PTE_INDEX_SIZE PTE_SHIFT @@ -55,26 +51,22 @@ extern int icache_44x_need_flush; #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) -#define pte_ERROR(e) \ - pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \ - (unsigned long long)pte_val(e)) #define pgd_ERROR(e) \ pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) -#ifndef __ASSEMBLY__ - -int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); -void unmap_kernel_page(unsigned long va); - -#endif /* !__ASSEMBLY__ */ - - /* * This is the bottom of the PKMAP area with HIGHMEM or an arbitrary * value (for now) on others, from where we can start layout kernel * virtual space that goes below PKMAP and FIXMAP */ -#include + +#define FIXADDR_SIZE 0 +#ifdef CONFIG_KASAN +#include +#define FIXADDR_TOP (KASAN_SHADOW_START - PAGE_SIZE) +#else +#define FIXADDR_TOP ((unsigned long)(-PAGE_SIZE)) +#endif /* * ioremap_bot starts at that address. Early ioremaps move down from there, @@ -151,7 +143,7 @@ void unmap_kernel_page(unsigned long va); * The mask covered by the RPN must be a ULL on 32-bit platforms with * 64-bit PTEs. */ -#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) +#ifdef CONFIG_PTE_64BIT #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) #define MAX_POSSIBLE_PHYSMEM_BITS 36 #else @@ -159,48 +151,8 @@ void unmap_kernel_page(unsigned long va); #define MAX_POSSIBLE_PHYSMEM_BITS 32 #endif -/* - * _PAGE_CHG_MASK masks of bits that are to be preserved across - * pgprot changes. - */ -#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) - #ifndef __ASSEMBLY__ -#define pte_clear(mm, addr, ptep) \ - do { pte_update(mm, addr, ptep, ~0, 0, 0); } while (0) - -#ifndef pte_mkwrite_novma -static inline pte_t pte_mkwrite_novma(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_RW); -} -#endif - -static inline pte_t pte_mkdirty(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_DIRTY); -} - -static inline pte_t pte_mkyoung(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_ACCESSED); -} - -#ifndef pte_wrprotect -static inline pte_t pte_wrprotect(pte_t pte) -{ - return __pte(pte_val(pte) & ~_PAGE_RW); -} -#endif - -#ifndef pte_mkexec -static inline pte_t pte_mkexec(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_EXEC); -} -#endif - #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) #define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK) @@ -209,141 +161,6 @@ static inline void pmd_clear(pmd_t *pmdp) *pmdp = __pmd(0); } -/* - * PTE updates. This function is called whenever an existing - * valid PTE is updated. This does -not- include set_pte_at() - * which nowadays only sets a new PTE. - * - * Depending on the type of MMU, we may need to use atomic updates - * and the PTE may be either 32 or 64 bit wide. In the later case, - * when using atomic updates, only the low part of the PTE is - * accessed atomically. - * - * In addition, on 44x, we also maintain a global flag indicating - * that an executable user mapping was modified, which is needed - * to properly flush the virtually tagged instruction cache of - * those implementations. - * - * On the 8xx, the page tables are a bit special. For 16k pages, we have - * 4 identical entries. For 512k pages, we have 128 entries as if it was - * 4k pages, but they are flagged as 512k pages for the hardware. - * For other page sizes, we have a single entry in the table. - */ -#ifdef CONFIG_PPC_8xx -static pmd_t *pmd_off(struct mm_struct *mm, unsigned long addr); -static int hugepd_ok(hugepd_t hpd); - -static int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge) -{ - if (!huge) - return PAGE_SIZE / SZ_4K; - else if (hugepd_ok(*((hugepd_t *)pmd))) - return 1; - else if (IS_ENABLED(CONFIG_PPC_4K_PAGES) && !(val & _PAGE_HUGE)) - return SZ_16K / SZ_4K; - else - return SZ_512K / SZ_4K; -} - -static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, - unsigned long clr, unsigned long set, int huge) -{ - pte_basic_t *entry = (pte_basic_t *)p; - pte_basic_t old = pte_val(*p); - pte_basic_t new = (old & ~(pte_basic_t)clr) | set; - int num, i; - pmd_t *pmd = pmd_off(mm, addr); - - num = number_of_cells_per_pte(pmd, new, huge); - - for (i = 0; i < num; i += PAGE_SIZE / SZ_4K, new += PAGE_SIZE) { - *entry++ = new; - if (IS_ENABLED(CONFIG_PPC_16K_PAGES) && num != 1) { - *entry++ = new; - *entry++ = new; - *entry++ = new; - } - } - - return old; -} - -#ifdef CONFIG_PPC_16K_PAGES -#define ptep_get ptep_get -static inline pte_t ptep_get(pte_t *ptep) -{ - pte_basic_t val = READ_ONCE(ptep->pte); - pte_t pte = {val, val, val, val}; - - return pte; -} -#endif /* CONFIG_PPC_16K_PAGES */ - -#else -static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, - unsigned long clr, unsigned long set, int huge) -{ - pte_basic_t old = pte_val(*p); - pte_basic_t new = (old & ~(pte_basic_t)clr) | set; - - *p = __pte(new); - -#ifdef CONFIG_44x - if ((old & _PAGE_USER) && (old & _PAGE_EXEC)) - icache_44x_need_flush = 1; -#endif - return old; -} -#endif - -#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG -static inline int __ptep_test_and_clear_young(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - unsigned long old; - old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); - return (old & _PAGE_ACCESSED) != 0; -} -#define ptep_test_and_clear_young(__vma, __addr, __ptep) \ - __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep) - -#define __HAVE_ARCH_PTEP_GET_AND_CLEAR -static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) -{ - return __pte(pte_update(mm, addr, ptep, ~0, 0, 0)); -} - -#define __HAVE_ARCH_PTEP_SET_WRPROTECT -#ifndef ptep_set_wrprotect -static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) -{ - pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); -} -#endif - -#ifndef __ptep_set_access_flags -static inline void __ptep_set_access_flags(struct vm_area_struct *vma, - pte_t *ptep, pte_t entry, - unsigned long address, - int psize) -{ - unsigned long set = pte_val(entry) & - (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); - int huge = psize > mmu_virtual_psize ? 1 : 0; - - pte_update(vma->vm_mm, address, ptep, 0, set, huge); - - flush_tlb_page(vma, address); -} -#endif - -static inline int pte_young(pte_t pte) -{ - return pte_val(pte) & _PAGE_ACCESSED; -} - /* * Note that on Book E processors, the pmd contains the kernel virtual * (lowmem) address of the pte page. The physical address is less useful diff --git a/arch/powerpc/include/asm/nohash/32/pte-40x.h b/arch/powerpc/include/asm/nohash/32/pte-40x.h index 6fe46e754556..d759cfd74754 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-40x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-40x.h @@ -42,10 +42,10 @@ #define _PAGE_PRESENT 0x002 /* software: PTE contains a translation */ #define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */ #define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */ -#define _PAGE_USER 0x010 /* matches one of the zone permission bits */ +#define _PAGE_READ 0x010 /* software: read permission */ #define _PAGE_SPECIAL 0x020 /* software: Special page */ #define _PAGE_DIRTY 0x080 /* software: dirty page */ -#define _PAGE_RW 0x100 /* hardware: WR, anded with dirty in exception */ +#define _PAGE_WRITE 0x100 /* hardware: WR, anded with dirty in exception */ #define _PAGE_EXEC 0x200 /* hardware: EX permission */ #define _PAGE_ACCESSED 0x400 /* software: R: page referenced */ @@ -55,11 +55,6 @@ /* cache related flags non existing on 40x */ #define _PAGE_COHERENT 0 -#define _PAGE_KERNEL_RO 0 -#define _PAGE_KERNEL_ROX _PAGE_EXEC -#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) -#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) - #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ #define _PMD_PRESENT_MASK _PMD_PRESENT #define _PMD_BAD 0x802 @@ -69,20 +64,10 @@ #define _PTE_NONE_MASK 0 -/* Until my rework is finished, 40x still needs atomic PTE updates */ -#define PTE_ATOMIC_UPDATES 1 - #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) #define _PAGE_BASE (_PAGE_BASE_NC) -/* Permission masks used to generate the __P and __S table */ -#define PAGE_NONE __pgprot(_PAGE_BASE) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#include #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_32_PTE_40x_H */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-44x.h b/arch/powerpc/include/asm/nohash/32/pte-44x.h index b7ed13cee137..851813725237 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-44x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-44x.h @@ -63,12 +63,12 @@ */ #define _PAGE_PRESENT 0x00000001 /* S: PTE valid */ -#define _PAGE_RW 0x00000002 /* S: Write permission */ +#define _PAGE_WRITE 0x00000002 /* S: Write permission */ #define _PAGE_EXEC 0x00000004 /* H: Execute permission */ -#define _PAGE_ACCESSED 0x00000008 /* S: Page referenced */ +#define _PAGE_READ 0x00000008 /* S: Read permission */ #define _PAGE_DIRTY 0x00000010 /* S: Page dirty */ #define _PAGE_SPECIAL 0x00000020 /* S: Special page */ -#define _PAGE_USER 0x00000040 /* S: User page */ +#define _PAGE_ACCESSED 0x00000040 /* S: Page referenced */ #define _PAGE_ENDIAN 0x00000080 /* H: E bit */ #define _PAGE_GUARDED 0x00000100 /* H: G bit */ #define _PAGE_COHERENT 0x00000200 /* H: M bit */ @@ -78,11 +78,6 @@ /* No page size encoding in the linux PTE */ #define _PAGE_PSIZE 0 -#define _PAGE_KERNEL_RO 0 -#define _PAGE_KERNEL_ROX _PAGE_EXEC -#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) -#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) - /* TODO: Add large page lowmem mapping support */ #define _PMD_PRESENT 0 #define _PMD_PRESENT_MASK (PAGE_MASK) @@ -105,14 +100,7 @@ #define _PAGE_BASE (_PAGE_BASE_NC) #endif -/* Permission masks used to generate the __P and __S table */ -#define PAGE_NONE __pgprot(_PAGE_BASE) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#include #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_32_PTE_44x_H */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-85xx.h b/arch/powerpc/include/asm/nohash/32/pte-85xx.h index 16451df5ddb0..653a342d3b25 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-85xx.h +++ b/arch/powerpc/include/asm/nohash/32/pte-85xx.h @@ -17,9 +17,9 @@ */ /* Definitions for FSL Book-E Cores */ -#define _PAGE_PRESENT 0x00001 /* S: PTE contains a translation */ -#define _PAGE_USER 0x00002 /* S: User page (maps to UR) */ -#define _PAGE_RW 0x00004 /* S: Write permission (SW) */ +#define _PAGE_READ 0x00001 /* H: Read permission (SR) */ +#define _PAGE_PRESENT 0x00002 /* S: PTE contains a translation */ +#define _PAGE_WRITE 0x00004 /* S: Write permission (SW) */ #define _PAGE_DIRTY 0x00008 /* S: Page dirty */ #define _PAGE_EXEC 0x00010 /* H: SX permission */ #define _PAGE_ACCESSED 0x00020 /* S: Page referenced */ @@ -31,11 +31,6 @@ #define _PAGE_WRITETHRU 0x00400 /* H: W bit */ #define _PAGE_SPECIAL 0x00800 /* S: Special page */ -#define _PAGE_KERNEL_RO 0 -#define _PAGE_KERNEL_ROX _PAGE_EXEC -#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) -#define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) - /* No page size encoding in the linux PTE */ #define _PAGE_PSIZE 0 @@ -61,14 +56,7 @@ #define _PAGE_BASE (_PAGE_BASE_NC) #endif -/* Permission masks used to generate the __P and __S table */ -#define PAGE_NONE __pgprot(_PAGE_BASE) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#include #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_NOHASH_32_PTE_FSL_85xx_H */ diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h index e6fe1d5731f2..137dc3c84e45 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h @@ -48,6 +48,11 @@ #define _PAGE_HUGE 0x0800 /* Copied to L1 PS bit 29 */ +#define _PAGE_NAX (_PAGE_NA | _PAGE_EXEC) +#define _PAGE_ROX (_PAGE_RO | _PAGE_EXEC) +#define _PAGE_RW 0 +#define _PAGE_RWX _PAGE_EXEC + /* cache related flags non existing on 8xx */ #define _PAGE_COHERENT 0 #define _PAGE_WRITETHRU 0 @@ -77,14 +82,7 @@ #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) #define _PAGE_BASE (_PAGE_BASE_NC) -/* Permission masks used to generate the __P and __S table */ -#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA) -#define PAGE_SHARED __pgprot(_PAGE_BASE) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_EXEC) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_RO) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_RO) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC) +#include #ifndef __ASSEMBLY__ static inline pte_t pte_wrprotect(pte_t pte) @@ -115,27 +113,6 @@ static inline pte_t pte_mkwrite_novma(pte_t pte) #define pte_mkwrite_novma pte_mkwrite_novma -static inline bool pte_user(pte_t pte) -{ - return !(pte_val(pte) & _PAGE_SH); -} - -#define pte_user pte_user - -static inline pte_t pte_mkprivileged(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_SH); -} - -#define pte_mkprivileged pte_mkprivileged - -static inline pte_t pte_mkuser(pte_t pte) -{ - return __pte(pte_val(pte) & ~_PAGE_SH); -} - -#define pte_mkuser pte_mkuser - static inline pte_t pte_mkhuge(pte_t pte) { return __pte(pte_val(pte) | _PAGE_SPS | _PAGE_HUGE); @@ -187,6 +164,63 @@ static inline unsigned long pte_leaf_size(pte_t pte) #define pte_leaf_size pte_leaf_size +/* + * On the 8xx, the page tables are a bit special. For 16k pages, we have + * 4 identical entries. For 512k pages, we have 128 entries as if it was + * 4k pages, but they are flagged as 512k pages for the hardware. + * For other page sizes, we have a single entry in the table. + */ +static pmd_t *pmd_off(struct mm_struct *mm, unsigned long addr); +static int hugepd_ok(hugepd_t hpd); + +static inline int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge) +{ + if (!huge) + return PAGE_SIZE / SZ_4K; + else if (hugepd_ok(*((hugepd_t *)pmd))) + return 1; + else if (IS_ENABLED(CONFIG_PPC_4K_PAGES) && !(val & _PAGE_HUGE)) + return SZ_16K / SZ_4K; + else + return SZ_512K / SZ_4K; +} + +static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, + unsigned long clr, unsigned long set, int huge) +{ + pte_basic_t *entry = (pte_basic_t *)p; + pte_basic_t old = pte_val(*p); + pte_basic_t new = (old & ~(pte_basic_t)clr) | set; + int num, i; + pmd_t *pmd = pmd_off(mm, addr); + + num = number_of_cells_per_pte(pmd, new, huge); + + for (i = 0; i < num; i += PAGE_SIZE / SZ_4K, new += PAGE_SIZE) { + *entry++ = new; + if (IS_ENABLED(CONFIG_PPC_16K_PAGES) && num != 1) { + *entry++ = new; + *entry++ = new; + *entry++ = new; + } + } + + return old; +} + +#define pte_update pte_update + +#ifdef CONFIG_PPC_16K_PAGES +#define ptep_get ptep_get +static inline pte_t ptep_get(pte_t *ptep) +{ + pte_basic_t val = READ_ONCE(ptep->pte); + pte_t pte = {val, val, val, val}; + + return pte; +} +#endif /* CONFIG_PPC_16K_PAGES */ + #endif #endif /* __KERNEL__ */ diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h index eb6891e34cbd..2202c78730e8 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable.h @@ -57,6 +57,7 @@ #define IOREMAP_START (ioremap_bot) #define IOREMAP_END (KERN_IO_START + KERN_IO_SIZE - FIXADDR_SIZE) #define FIXADDR_SIZE SZ_32M +#define FIXADDR_TOP (IOREMAP_END + FIXADDR_SIZE) /* * Defines the address of the vmemap area, in its own region on @@ -74,37 +75,11 @@ #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) -/* - * _PAGE_CHG_MASK masks of bits that are to be preserved across - * pgprot changes. - */ -#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) - #define H_PAGE_4K_PFN 0 #ifndef __ASSEMBLY__ /* pte_clear moved to later in this file */ -static inline pte_t pte_mkwrite_novma(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_RW); -} - -static inline pte_t pte_mkdirty(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_DIRTY); -} - -static inline pte_t pte_mkyoung(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_ACCESSED); -} - -static inline pte_t pte_wrprotect(pte_t pte) -{ - return __pte(pte_val(pte) & ~_PAGE_RW); -} - #define PMD_BAD_BITS (PTE_TABLE_SIZE-1) #define PUD_BAD_BITS (PMD_TABLE_SIZE-1) @@ -170,107 +145,20 @@ static inline void p4d_set(p4d_t *p4dp, unsigned long val) *p4dp = __p4d(val); } -/* Atomic PTE updates */ -static inline unsigned long pte_update(struct mm_struct *mm, - unsigned long addr, - pte_t *ptep, unsigned long clr, - unsigned long set, - int huge) -{ - unsigned long old = pte_val(*ptep); - *ptep = __pte((old & ~clr) | set); - - /* huge pages use the old page table lock */ - if (!huge) - assert_pte_locked(mm, addr); - - return old; -} - -static inline int pte_young(pte_t pte) -{ - return pte_val(pte) & _PAGE_ACCESSED; -} - -static inline int __ptep_test_and_clear_young(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - unsigned long old; - - if (!pte_young(*ptep)) - return 0; - old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); - return (old & _PAGE_ACCESSED) != 0; -} -#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG -#define ptep_test_and_clear_young(__vma, __addr, __ptep) \ -({ \ - int __r; \ - __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \ - __r; \ -}) - -#define __HAVE_ARCH_PTEP_SET_WRPROTECT -static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) -{ - - if ((pte_val(*ptep) & _PAGE_RW) == 0) - return; - - pte_update(mm, addr, ptep, _PAGE_RW, 0, 0); -} - #define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - if ((pte_val(*ptep) & _PAGE_RW) == 0) - return; - - pte_update(mm, addr, ptep, _PAGE_RW, 0, 1); + pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1); } #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH #define ptep_clear_flush_young(__vma, __address, __ptep) \ ({ \ - int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \ - __ptep); \ + int __young = ptep_test_and_clear_young(__vma, __address, __ptep);\ __young; \ }) -#define __HAVE_ARCH_PTEP_GET_AND_CLEAR -static inline pte_t ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) -{ - unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0); - return __pte(old); -} - -static inline void pte_clear(struct mm_struct *mm, unsigned long addr, - pte_t * ptep) -{ - pte_update(mm, addr, ptep, ~0UL, 0, 0); -} - - -/* Set the dirty and/or accessed bits atomically in a linux PTE */ -static inline void __ptep_set_access_flags(struct vm_area_struct *vma, - pte_t *ptep, pte_t entry, - unsigned long address, - int psize) -{ - unsigned long bits = pte_val(entry) & - (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); - - unsigned long old = pte_val(*ptep); - *ptep = __pte(old | bits); - - flush_tlb_page(vma, address); -} - -#define pte_ERROR(e) \ - pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) #define pgd_ERROR(e) \ @@ -310,8 +198,6 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, /* We borrow MSB 56 (LSB 7) to store the exclusive marker in swap PTEs. */ #define _PAGE_SWP_EXCLUSIVE 0x80 -int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot); -void unmap_kernel_page(unsigned long va); extern int __meminit vmemmap_create_mapping(unsigned long start, unsigned long page_size, unsigned long phys); diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index c721478c5934..427db14292c9 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h @@ -2,12 +2,23 @@ #ifndef _ASM_POWERPC_NOHASH_PGTABLE_H #define _ASM_POWERPC_NOHASH_PGTABLE_H +#ifndef __ASSEMBLY__ +static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, + unsigned long clr, unsigned long set, int huge); +#endif + #if defined(CONFIG_PPC64) #include #else #include #endif +/* + * _PAGE_CHG_MASK masks of bits that are to be preserved across + * pgprot changes. + */ +#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) + /* Permission masks used for kernel mappings */ #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE) @@ -18,16 +29,136 @@ #ifndef __ASSEMBLY__ +extern int icache_44x_need_flush; + +/* + * PTE updates. This function is called whenever an existing + * valid PTE is updated. This does -not- include set_pte_at() + * which nowadays only sets a new PTE. + * + * Depending on the type of MMU, we may need to use atomic updates + * and the PTE may be either 32 or 64 bit wide. In the later case, + * when using atomic updates, only the low part of the PTE is + * accessed atomically. + * + * In addition, on 44x, we also maintain a global flag indicating + * that an executable user mapping was modified, which is needed + * to properly flush the virtually tagged instruction cache of + * those implementations. + */ +#ifndef pte_update +static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, + unsigned long clr, unsigned long set, int huge) +{ + pte_basic_t old = pte_val(*p); + pte_basic_t new = (old & ~(pte_basic_t)clr) | set; + + if (new == old) + return old; + + *p = __pte(new); + + if (IS_ENABLED(CONFIG_44x) && !is_kernel_addr(addr) && (old & _PAGE_EXEC)) + icache_44x_need_flush = 1; + + /* huge pages use the old page table lock */ + if (!huge) + assert_pte_locked(mm, addr); + + return old; +} +#endif + +static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, + unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + old = pte_update(vma->vm_mm, addr, ptep, _PAGE_ACCESSED, 0, 0); + + return (old & _PAGE_ACCESSED) != 0; +} +#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG + +#ifndef ptep_set_wrprotect +static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0); +} +#endif +#define __HAVE_ARCH_PTEP_SET_WRPROTECT + +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + return __pte(pte_update(mm, addr, ptep, ~0UL, 0, 0)); +} +#define __HAVE_ARCH_PTEP_GET_AND_CLEAR + +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + pte_update(mm, addr, ptep, ~0UL, 0, 0); +} + +/* Set the dirty and/or accessed bits atomically in a linux PTE */ +#ifndef __ptep_set_access_flags +static inline void __ptep_set_access_flags(struct vm_area_struct *vma, + pte_t *ptep, pte_t entry, + unsigned long address, + int psize) +{ + unsigned long set = pte_val(entry) & + (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); + int huge = psize > mmu_virtual_psize ? 1 : 0; + + pte_update(vma->vm_mm, address, ptep, 0, set, huge); + + flush_tlb_page(vma, address); +} +#endif + /* Generic accessors to PTE bits */ +#ifndef pte_mkwrite_novma +static inline pte_t pte_mkwrite_novma(pte_t pte) +{ + /* + * write implies read, hence set both + */ + return __pte(pte_val(pte) | _PAGE_RW); +} +#endif + +static inline pte_t pte_mkdirty(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_DIRTY); +} + +static inline pte_t pte_mkyoung(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_ACCESSED); +} + +#ifndef pte_wrprotect +static inline pte_t pte_wrprotect(pte_t pte) +{ + return __pte(pte_val(pte) & ~_PAGE_WRITE); +} +#endif + +#ifndef pte_mkexec +static inline pte_t pte_mkexec(pte_t pte) +{ + return __pte(pte_val(pte) | _PAGE_EXEC); +} +#endif + #ifndef pte_write static inline int pte_write(pte_t pte) { - return pte_val(pte) & _PAGE_RW; + return pte_val(pte) & _PAGE_WRITE; } #endif -#ifndef pte_read -static inline int pte_read(pte_t pte) { return 1; } -#endif static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } @@ -35,23 +166,6 @@ static inline bool pte_hashpte(pte_t pte) { return false; } static inline bool pte_ci(pte_t pte) { return pte_val(pte) & _PAGE_NO_CACHE; } static inline bool pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } -#ifdef CONFIG_NUMA_BALANCING -/* - * These work without NUMA balancing but the kernel does not care. See the - * comment in include/linux/pgtable.h . On powerpc, this will only - * work for user pages and always return true for kernel pages. - */ -static inline int pte_protnone(pte_t pte) -{ - return pte_present(pte) && !pte_user(pte); -} - -static inline int pmd_protnone(pmd_t pmd) -{ - return pte_protnone(pmd_pte(pmd)); -} -#endif /* CONFIG_NUMA_BALANCING */ - static inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; @@ -62,15 +176,20 @@ static inline bool pte_hw_valid(pte_t pte) return pte_val(pte) & _PAGE_PRESENT; } -/* - * Don't just check for any non zero bits in __PAGE_USER, since for book3e - * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in - * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too. - */ -#ifndef pte_user -static inline bool pte_user(pte_t pte) +static inline int pte_young(pte_t pte) { - return (pte_val(pte) & _PAGE_USER) == _PAGE_USER; + return pte_val(pte) & _PAGE_ACCESSED; +} + +/* + * Don't just check for any non zero bits in __PAGE_READ, since for book3e + * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in + * _PAGE_READ. Need to explicitly match _PAGE_BAP_UR bit in that case too. + */ +#ifndef pte_read +static inline bool pte_read(pte_t pte) +{ + return (pte_val(pte) & _PAGE_READ) == _PAGE_READ; } #endif @@ -82,10 +201,10 @@ static inline bool pte_user(pte_t pte) static inline bool pte_access_permitted(pte_t pte, bool write) { /* - * A read-only access is controlled by _PAGE_USER bit. - * We have _PAGE_READ set for WRITE and EXECUTE + * A read-only access is controlled by _PAGE_READ bit. + * We have _PAGE_READ set for WRITE */ - if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) + if (!pte_present(pte) || !pte_read(pte)) return false; if (write && !pte_write(pte)) @@ -132,20 +251,6 @@ static inline pte_t pte_mkhuge(pte_t pte) } #endif -#ifndef pte_mkprivileged -static inline pte_t pte_mkprivileged(pte_t pte) -{ - return __pte(pte_val(pte) & ~_PAGE_USER); -} -#endif - -#ifndef pte_mkuser -static inline pte_t pte_mkuser(pte_t pte) -{ - return __pte(pte_val(pte) | _PAGE_USER); -} -#endif - static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); @@ -207,11 +312,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, mb(); } - -#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, - pte_t *ptep, pte_t entry, int dirty); - /* * Macro to mark a page protection value as "uncacheable". */ @@ -240,11 +340,6 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre #define pgprot_writecombine pgprot_noncached_wc -struct file; -extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, - unsigned long size, pgprot_t vma_prot); -#define __HAVE_PHYS_MEM_ACCESS_PROT - #ifdef CONFIG_HUGETLB_PAGE static inline int hugepd_ok(hugepd_t hpd) { @@ -269,20 +364,8 @@ static inline int pud_huge(pud_t pud) #define is_hugepd(hpd) (hugepd_ok(hpd)) #endif -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to ensure coherency between the i-cache and d-cache - * for the page which has just been mapped in. - */ -#if defined(CONFIG_PPC_E500) && defined(CONFIG_HUGETLB_PAGE) -void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, - unsigned long address, pte_t *ptep, unsigned int nr); -#else -static inline void update_mmu_cache_range(struct vm_fault *vmf, - struct vm_area_struct *vma, unsigned long address, - pte_t *ptep, unsigned int nr) {} -#endif +int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); +void unmap_kernel_page(unsigned long va); #endif /* __ASSEMBLY__ */ #endif diff --git a/arch/powerpc/include/asm/nohash/pte-e500.h b/arch/powerpc/include/asm/nohash/pte-e500.h index d8924cbd61e4..f516f0b5b7a8 100644 --- a/arch/powerpc/include/asm/nohash/pte-e500.h +++ b/arch/powerpc/include/asm/nohash/pte-e500.h @@ -48,13 +48,20 @@ /* "Higher level" linux bit combinations */ #define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */ -#define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ +#define _PAGE_READ (_PAGE_BAP_SR | _PAGE_BAP_UR) /* User read permission */ +#define _PAGE_WRITE (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */ + #define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY) #define _PAGE_KERNEL_RO (_PAGE_BAP_SR) #define _PAGE_KERNEL_RWX (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY | _PAGE_BAP_SX) #define _PAGE_KERNEL_ROX (_PAGE_BAP_SR | _PAGE_BAP_SX) -#define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */ -#define _PAGE_PRIVILEGED (_PAGE_BAP_SR) + +#define _PAGE_NA 0 +#define _PAGE_NAX _PAGE_BAP_UX +#define _PAGE_RO _PAGE_READ +#define _PAGE_ROX (_PAGE_READ | _PAGE_BAP_UX) +#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE) +#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_BAP_UX) #define _PAGE_SPECIAL _PAGE_SW0 @@ -89,36 +96,12 @@ #define _PAGE_BASE (_PAGE_BASE_NC) #endif -/* Permission masks used to generate the __P and __S table */ -#define PAGE_NONE __pgprot(_PAGE_BASE) -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX) -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX) -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX) +#include #ifndef __ASSEMBLY__ -static inline pte_t pte_mkprivileged(pte_t pte) -{ - return __pte((pte_val(pte) & ~_PAGE_USER) | _PAGE_PRIVILEGED); -} - -#define pte_mkprivileged pte_mkprivileged - -static inline pte_t pte_mkuser(pte_t pte) -{ - return __pte((pte_val(pte) & ~_PAGE_PRIVILEGED) | _PAGE_USER); -} - -#define pte_mkuser pte_mkuser - static inline pte_t pte_mkexec(pte_t pte) { - if (pte_val(pte) & _PAGE_BAP_UR) - return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX); - else - return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX); + return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX); } #define pte_mkexec pte_mkexec diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index a9b31cc258fc..b66b0c615f4f 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h @@ -227,7 +227,7 @@ int64_t opal_pci_set_power_state(uint64_t async_token, uint64_t id, uint64_t data); int64_t opal_pci_poll2(uint64_t id, uint64_t data); -int64_t opal_int_get_xirr(uint32_t *out_xirr, bool just_poll); +int64_t opal_int_get_xirr(__be32 *out_xirr, bool just_poll); int64_t opal_int_set_cppr(uint8_t cppr); int64_t opal_int_eoi(uint32_t xirr); int64_t opal_int_set_mfrr(uint32_t cpu, uint8_t mfrr); diff --git a/arch/powerpc/include/asm/paravirt.h b/arch/powerpc/include/asm/paravirt.h index e08513d73119..ac4279208d63 100644 --- a/arch/powerpc/include/asm/paravirt.h +++ b/arch/powerpc/include/asm/paravirt.h @@ -71,6 +71,11 @@ static inline void yield_to_any(void) { plpar_hcall_norets_notrace(H_CONFER, -1, 0); } + +static inline bool is_vcpu_idle(int vcpu) +{ + return lppaca_of(vcpu).idle; +} #else static inline bool is_shared_processor(void) { @@ -100,6 +105,10 @@ static inline void prod_cpu(int cpu) ___bad_prod_cpu(); /* This would be a bug */ } +static inline bool is_vcpu_idle(int vcpu) +{ + return false; +} #endif #define vcpu_is_preempted vcpu_is_preempted @@ -121,9 +130,23 @@ static inline bool vcpu_is_preempted(int cpu) if (!is_shared_processor()) return false; + /* + * If the hypervisor has dispatched the target CPU on a physical + * processor, then the target CPU is definitely not preempted. + */ + if (!(yield_count_of(cpu) & 1)) + return false; + + /* + * If the target CPU has yielded to Hypervisor but OS has not + * requested idle then the target CPU is definitely preempted. + */ + if (!is_vcpu_idle(cpu)) + return true; + #ifdef CONFIG_PPC_SPLPAR if (!is_kvm_guest()) { - int first_cpu; + int first_cpu, i; /* * The result of vcpu_is_preempted() is used in a @@ -149,11 +172,29 @@ static inline bool vcpu_is_preempted(int cpu) */ if (cpu_first_thread_sibling(cpu) == first_cpu) return false; + + /* + * If any of the threads of the target CPU's core are not + * preempted or ceded, then consider target CPU to be + * non-preempted. + */ + first_cpu = cpu_first_thread_sibling(cpu); + for (i = first_cpu; i < first_cpu + threads_per_core; i++) { + if (i == cpu) + continue; + if (!(yield_count_of(i) & 1)) + return false; + if (!is_vcpu_idle(i)) + return true; + } } #endif - if (yield_count_of(cpu) & 1) - return true; + /* + * None of the threads in target CPU's core are running but none of + * them were preempted too. Hence assume the target CPU to be + * non-preempted. + */ return false; } diff --git a/arch/powerpc/include/asm/pgtable-masks.h b/arch/powerpc/include/asm/pgtable-masks.h new file mode 100644 index 000000000000..6e8e2db26a5a --- /dev/null +++ b/arch/powerpc/include/asm/pgtable-masks.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_PGTABLE_MASKS_H +#define _ASM_POWERPC_PGTABLE_MASKS_H + +#ifndef _PAGE_NA +#define _PAGE_NA 0 +#define _PAGE_NAX _PAGE_EXEC +#define _PAGE_RO _PAGE_READ +#define _PAGE_ROX (_PAGE_READ | _PAGE_EXEC) +#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE) +#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC) +#endif + +/* Permission flags for kernel mappings */ +#ifndef _PAGE_KERNEL_RO +#define _PAGE_KERNEL_RO _PAGE_RO +#define _PAGE_KERNEL_ROX _PAGE_ROX +#define _PAGE_KERNEL_RW (_PAGE_RW | _PAGE_DIRTY) +#define _PAGE_KERNEL_RWX (_PAGE_RWX | _PAGE_DIRTY) +#endif + +/* Permission masks used to generate the __P and __S table */ +#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA) +#define PAGE_EXECONLY_X __pgprot(_PAGE_BASE | _PAGE_NAX) +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RWX) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_RO) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_ROX) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_RO) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_ROX) + +#endif /* _ASM_POWERPC_PGTABLE_MASKS_H */ diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index d0ee46de248e..2bfb7dd3b49e 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -71,6 +71,12 @@ static inline pgprot_t pte_pgprot(pte_t pte) return __pgprot(pte_flags); } +static inline pgprot_t pgprot_nx(pgprot_t prot) +{ + return pte_pgprot(pte_exprotect(__pte(pgprot_val(prot)))); +} +#define pgprot_nx pgprot_nx + #ifndef pmd_page_vaddr static inline const void *pmd_page_vaddr(pmd_t pmd) { @@ -110,6 +116,35 @@ void mark_initmem_nx(void); static inline void mark_initmem_nx(void) { } #endif +#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, + pte_t *ptep, pte_t entry, int dirty); + +struct file; +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); +#define __HAVE_PHYS_MEM_ACCESS_PROT + +void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep); + +/* + * This gets called at the end of handling a page fault, when + * the kernel has put a new PTE into the page table for the process. + * We use it to ensure coherency between the i-cache and d-cache + * for the page which has just been mapped in. + * On machines which use an MMU hash table, we use this to put a + * corresponding HPTE into the hash table ahead of time, instead of + * waiting for the inevitable extra hash-table miss exception. + */ +static inline void update_mmu_cache_range(struct vm_fault *vmf, + struct vm_area_struct *vma, unsigned long address, + pte_t *ptep, unsigned int nr) +{ + if ((mmu_has_feature(MMU_FTR_HPTE_TABLE) && !radix_enabled()) || + (IS_ENABLED(CONFIG_PPC_E500) && IS_ENABLED(CONFIG_HUGETLB_PAGE))) + __update_mmu_cache(vma, address, ptep); +} + /* * When used, PTE_FRAG_NR is defined in subarch pgtable.h * so we are sure it is included when arriving here. diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h index fe3d0ea0058a..b3ee44a40c2f 100644 --- a/arch/powerpc/include/asm/plpar_wrappers.h +++ b/arch/powerpc/include/asm/plpar_wrappers.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -343,6 +344,212 @@ static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p) return rc; } +static inline long plpar_guest_create(unsigned long flags, unsigned long *guest_id) +{ + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + unsigned long token; + long rc; + + token = -1UL; + do { + rc = plpar_hcall(H_GUEST_CREATE, retbuf, flags, token); + if (rc == H_SUCCESS) + *guest_id = retbuf[0]; + + if (rc == H_BUSY) { + token = retbuf[0]; + cond_resched(); + } + + if (H_IS_LONG_BUSY(rc)) { + token = retbuf[0]; + msleep(get_longbusy_msecs(rc)); + rc = H_BUSY; + } + + } while (rc == H_BUSY); + + return rc; +} + +static inline long plpar_guest_create_vcpu(unsigned long flags, + unsigned long guest_id, + unsigned long vcpu_id) +{ + long rc; + + do { + rc = plpar_hcall_norets(H_GUEST_CREATE_VCPU, 0, guest_id, vcpu_id); + + if (rc == H_BUSY) + cond_resched(); + + if (H_IS_LONG_BUSY(rc)) { + msleep(get_longbusy_msecs(rc)); + rc = H_BUSY; + } + + } while (rc == H_BUSY); + + return rc; +} + +static inline long plpar_guest_set_state(unsigned long flags, + unsigned long guest_id, + unsigned long vcpu_id, + unsigned long data_buffer, + unsigned long data_size, + unsigned long *failed_index) +{ + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + long rc; + + while (true) { + rc = plpar_hcall(H_GUEST_SET_STATE, retbuf, flags, guest_id, + vcpu_id, data_buffer, data_size); + + if (rc == H_BUSY) { + cpu_relax(); + continue; + } + + if (H_IS_LONG_BUSY(rc)) { + mdelay(get_longbusy_msecs(rc)); + continue; + } + + if (rc == H_INVALID_ELEMENT_ID) + *failed_index = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_SIZE) + *failed_index = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_VALUE) + *failed_index = retbuf[0]; + + break; + } + + return rc; +} + +static inline long plpar_guest_get_state(unsigned long flags, + unsigned long guest_id, + unsigned long vcpu_id, + unsigned long data_buffer, + unsigned long data_size, + unsigned long *failed_index) +{ + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + long rc; + + while (true) { + rc = plpar_hcall(H_GUEST_GET_STATE, retbuf, flags, guest_id, + vcpu_id, data_buffer, data_size); + + if (rc == H_BUSY) { + cpu_relax(); + continue; + } + + if (H_IS_LONG_BUSY(rc)) { + mdelay(get_longbusy_msecs(rc)); + continue; + } + + if (rc == H_INVALID_ELEMENT_ID) + *failed_index = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_SIZE) + *failed_index = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_VALUE) + *failed_index = retbuf[0]; + + break; + } + + return rc; +} + +static inline long plpar_guest_run_vcpu(unsigned long flags, unsigned long guest_id, + unsigned long vcpu_id, int *trap, + unsigned long *failed_index) +{ + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + long rc; + + rc = plpar_hcall(H_GUEST_RUN_VCPU, retbuf, flags, guest_id, vcpu_id); + if (rc == H_SUCCESS) + *trap = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_ID) + *failed_index = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_SIZE) + *failed_index = retbuf[0]; + else if (rc == H_INVALID_ELEMENT_VALUE) + *failed_index = retbuf[0]; + + return rc; +} + +static inline long plpar_guest_delete(unsigned long flags, u64 guest_id) +{ + long rc; + + do { + rc = plpar_hcall_norets(H_GUEST_DELETE, flags, guest_id); + if (rc == H_BUSY) + cond_resched(); + + if (H_IS_LONG_BUSY(rc)) { + msleep(get_longbusy_msecs(rc)); + rc = H_BUSY; + } + + } while (rc == H_BUSY); + + return rc; +} + +static inline long plpar_guest_set_capabilities(unsigned long flags, + unsigned long capabilities) +{ + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + long rc; + + do { + rc = plpar_hcall(H_GUEST_SET_CAPABILITIES, retbuf, flags, capabilities); + if (rc == H_BUSY) + cond_resched(); + + if (H_IS_LONG_BUSY(rc)) { + msleep(get_longbusy_msecs(rc)); + rc = H_BUSY; + } + } while (rc == H_BUSY); + + return rc; +} + +static inline long plpar_guest_get_capabilities(unsigned long flags, + unsigned long *capabilities) +{ + unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; + long rc; + + do { + rc = plpar_hcall(H_GUEST_GET_CAPABILITIES, retbuf, flags); + if (rc == H_BUSY) + cond_resched(); + + if (H_IS_LONG_BUSY(rc)) { + msleep(get_longbusy_msecs(rc)); + rc = H_BUSY; + } + } while (rc == H_BUSY); + + if (rc == H_SUCCESS) + *capabilities = retbuf[0]; + + return rc; +} + /* * Wrapper to H_RPT_INVALIDATE hcall that handles return values appropriately * @@ -355,7 +562,7 @@ static inline long plpar_get_cpu_characteristics(struct h_cpu_char_result *p) * error recovery of killing the process/guest will be eventually * needed. */ -static inline long pseries_rpt_invalidate(u32 pid, u64 target, u64 type, +static inline long pseries_rpt_invalidate(u64 pid, u64 target, u64 type, u64 page_sizes, u64 start, u64 end) { long rc; @@ -401,12 +608,68 @@ static inline long plpar_pte_read_4(unsigned long flags, unsigned long ptex, return 0; } -static inline long pseries_rpt_invalidate(u32 pid, u64 target, u64 type, +static inline long pseries_rpt_invalidate(u64 pid, u64 target, u64 type, u64 page_sizes, u64 start, u64 end) { return 0; } +static inline long plpar_guest_create_vcpu(unsigned long flags, + unsigned long guest_id, + unsigned long vcpu_id) +{ + return 0; +} + +static inline long plpar_guest_get_state(unsigned long flags, + unsigned long guest_id, + unsigned long vcpu_id, + unsigned long data_buffer, + unsigned long data_size, + unsigned long *failed_index) +{ + return 0; +} + +static inline long plpar_guest_set_state(unsigned long flags, + unsigned long guest_id, + unsigned long vcpu_id, + unsigned long data_buffer, + unsigned long data_size, + unsigned long *failed_index) +{ + return 0; +} + +static inline long plpar_guest_run_vcpu(unsigned long flags, unsigned long guest_id, + unsigned long vcpu_id, int *trap, + unsigned long *failed_index) +{ + return 0; +} + +static inline long plpar_guest_create(unsigned long flags, unsigned long *guest_id) +{ + return 0; +} + +static inline long plpar_guest_delete(unsigned long flags, u64 guest_id) +{ + return 0; +} + +static inline long plpar_guest_get_capabilities(unsigned long flags, + unsigned long *capabilities) +{ + return 0; +} + +static inline long plpar_guest_set_capabilities(unsigned long flags, + unsigned long capabilities) +{ + return 0; +} + #endif /* CONFIG_PPC_PSERIES */ #endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */ diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 9db8b16567e2..ea8f91fbc62f 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -397,6 +397,23 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, return 0; } +/** + * regs_get_kernel_argument() - get Nth function argument in kernel + * @regs: pt_regs of that context + * @n: function argument number (start from 0) + * + * We support up to 8 arguments and assume they are sent in through the GPRs. + * This will fail for fp/vector arguments, but those aren't usually found in + * kernel code. This is expected to be called from kprobes or ftrace with regs. + */ +static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs, unsigned int n) +{ +#define NR_REG_ARGUMENTS 8 + if (n < NR_REG_ARGUMENTS) + return regs_get_register(regs, offsetof(struct pt_regs, gpr[3 + n])); + return 0; +} + #endif /* __ASSEMBLY__ */ #ifndef __powerpc64__ diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index fb725ec77926..f1f9890f50d3 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -374,7 +374,7 @@ copy_mc_to_user(void __user *to, const void *from, unsigned long n) if (check_copy_size(from, n, true)) { if (access_ok(to, n)) { allow_write_to_user(to, n); - n = copy_mc_generic((void *)to, from, n); + n = copy_mc_generic((void __force *)to, from, n); prevent_write_to_user(to, n); } } diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 19e46fd623b0..7f63f1cdc6c3 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -41,10 +42,6 @@ static unsigned char *logicalDisplayBase __force_data; unsigned long disp_BAT[2] __initdata = {0, 0}; -#define cmapsz (16*256) - -static unsigned char vga_font[cmapsz]; - static int boot_text_mapped __force_data; extern void rmci_on(void); @@ -407,7 +404,7 @@ static unsigned int expand_bits_16[4] = { }; -static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) +static void draw_byte_32(const unsigned char *font, unsigned int *base, int rb) { int l, bits; int fg = 0xFFFFFFFFUL; @@ -428,7 +425,7 @@ static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) } } -static inline void draw_byte_16(unsigned char *font, unsigned int *base, int rb) +static inline void draw_byte_16(const unsigned char *font, unsigned int *base, int rb) { int l, bits; int fg = 0xFFFFFFFFUL; @@ -446,7 +443,7 @@ static inline void draw_byte_16(unsigned char *font, unsigned int *base, int rb) } } -static inline void draw_byte_8(unsigned char *font, unsigned int *base, int rb) +static inline void draw_byte_8(const unsigned char *font, unsigned int *base, int rb) { int l, bits; int fg = 0x0F0F0F0FUL; @@ -465,7 +462,8 @@ static inline void draw_byte_8(unsigned char *font, unsigned int *base, int rb) static noinline void draw_byte(unsigned char c, long locX, long locY) { unsigned char *base = calc_base(locX << 3, locY << 4); - unsigned char *font = &vga_font[((unsigned int)c) * 16]; + unsigned int font_index = c * 16; + const unsigned char *font = font_sun_8x16.data + font_index; int rb = dispDeviceRowBytes; rmci_maybe_on(); @@ -583,349 +581,3 @@ void __init udbg_init_btext(void) */ udbg_putc = btext_drawchar; } - -static unsigned char vga_font[cmapsz] = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, -0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, -0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, -0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, -0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, -0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, -0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, -0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, -0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, -0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, -0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, -0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, -0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, -0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, -0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, -0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, -0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, -0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, -0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, -0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, -0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, -0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, -0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, -0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, -0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, -0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, -0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, -0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, -0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, -0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, -0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, -0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, -0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, -0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, -0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, -0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, -0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, -0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, -0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, -0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, -0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, -0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, -0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, -0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, -0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, -0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, -0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, -0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, -0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, -0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, -0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, -0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, -0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, -0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, -0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, -0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, -0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, -0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, -0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, -0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, -0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, -0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, -0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, -0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, -0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, -0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, -0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, -0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, -0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, -0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, -0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, -0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, -0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, -0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, -0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, -0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, -0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, -0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, -0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, -0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, -0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, -0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, -0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, -0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, -0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, -0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, -0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, -0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, -0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, -0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, -0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, -0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, -0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, -0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, -}; - diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 9a3b85bfc83f..2086fa6cdc25 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef DEBUG #include @@ -92,6 +93,17 @@ ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn, return csize; } +/* + * Return true only when kexec based kernel dump capturing method is used. + * This ensures all restritions applied for kdump case are not automatically + * applied for fadump case. + */ +bool is_kdump_kernel(void) +{ + return !is_fadump_active() && elfcorehdr_addr != ELFCORE_ADDR_MAX; +} +EXPORT_SYMBOL_GPL(is_kdump_kernel); + #ifdef CONFIG_PPC_RTAS /* * The crashkernel region will almost always overlap the RTAS region, so diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 438568a472d0..48773d2d9be3 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c @@ -39,7 +39,7 @@ static int eeh_result_priority(enum pci_ers_result result) case PCI_ERS_RESULT_NEED_RESET: return 6; default: - WARN_ONCE(1, "Unknown pci_ers_result value: %d\n", (int)result); + WARN_ONCE(1, "Unknown pci_ers_result value: %d\n", result); return 0; } }; @@ -60,7 +60,7 @@ static const char *pci_ers_result_name(enum pci_ers_result result) case PCI_ERS_RESULT_NO_AER_DRIVER: return "no AER driver"; default: - WARN_ONCE(1, "Unknown result type: %d\n", (int)result); + WARN_ONCE(1, "Unknown result type: %d\n", result); return "unknown"; } }; diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index b32e7b2ebdcf..9fc90410b385 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S @@ -312,13 +312,13 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt) rlwimi r11, r10, 22, 20, 29 /* Compute PTE address */ lwz r11, 0(r11) /* Get Linux PTE */ - li r9, _PAGE_PRESENT | _PAGE_ACCESSED + li r9, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ andc. r9, r9, r11 /* Check permission */ bne 5f - rlwinm r9, r11, 1, _PAGE_RW /* dirty => rw */ - and r9, r9, r11 /* hwwrite = dirty & rw */ - rlwimi r11, r9, 0, _PAGE_RW /* replace rw by hwwrite */ + rlwinm r9, r11, 1, _PAGE_WRITE /* dirty => w */ + and r9, r9, r11 /* hwwrite = dirty & w */ + rlwimi r11, r9, 0, _PAGE_WRITE /* replace w by hwwrite */ /* Create TLB tag. This is the faulting address plus a static * set of bits. These are size, valid, E, U0. @@ -400,9 +400,9 @@ _ASM_NOKPROBE_SYMBOL(\name\()_virt) andc. r9, r9, r11 /* Check permission */ bne 5f - rlwinm r9, r11, 1, _PAGE_RW /* dirty => rw */ - and r9, r9, r11 /* hwwrite = dirty & rw */ - rlwimi r11, r9, 0, _PAGE_RW /* replace rw by hwwrite */ + rlwinm r9, r11, 1, _PAGE_WRITE /* dirty => w */ + and r9, r9, r11 /* hwwrite = dirty & w */ + rlwimi r11, r9, 0, _PAGE_WRITE /* replace w by hwwrite */ /* Create TLB tag. This is the faulting address plus a static * set of bits. These are size, valid, E, U0. @@ -561,10 +561,11 @@ finish_tlb_load: /* * Clear out the software-only bits in the PTE to generate the * TLB_DATA value. These are the bottom 2 bits of the RPM, the - * top 3 bits of the zone field, and M. + * 4 bits of the zone field, and M. */ - li r9, 0x0ce2 + li r9, 0x0cf2 andc r11, r11, r9 + rlwimi r11, r10, 8, 24, 27 /* Copy 4 upper address bit into zone */ /* load the next available TLB index. */ lwz r9, tlb_4xx_index@l(0) diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index a3197c9f721c..25642e802ed3 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -314,8 +314,8 @@ interrupt_base: * kernel page tables. */ lis r11, PAGE_OFFSET@h - cmplw r10, r11 - blt+ 3f + cmplw cr7, r10, r11 + blt+ cr7, 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l @@ -342,7 +342,7 @@ interrupt_base: mtspr SPRN_MMUCR,r12 /* Mask of required permission bits. Note that while we - * do copy ESR:ST to _PAGE_RW position as trying to write + * do copy ESR:ST to _PAGE_WRITE position as trying to write * to an RO page is pretty common, we don't do it with * _PAGE_DIRTY. We could do it, but it's a fairly rare * event so I'd rather take the overhead when it happens @@ -355,7 +355,7 @@ interrupt_base: * place or can we save a couple of instructions here ? */ mfspr r12,SPRN_ESR - li r13,_PAGE_PRESENT|_PAGE_ACCESSED + li r13,_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_READ rlwimi r13,r12,10,30,30 /* Load the PTE */ @@ -428,8 +428,8 @@ interrupt_base: * kernel page tables. */ lis r11, PAGE_OFFSET@h - cmplw r10, r11 - blt+ 3f + cmplw cr7, r10, r11 + blt+ cr7, 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l @@ -515,6 +515,7 @@ interrupt_base: * r11 - PTE high word value * r12 - PTE low word value * r13 - TLB index + * cr7 - Result of comparison with PAGE_OFFSET * MMUCR - loaded with proper value when we get here * Upon exit, we reload everything and RFI. */ @@ -533,11 +534,10 @@ finish_tlb_load_44x: tlbwe r10,r13,PPC44x_TLB_PAGEID /* Write PAGEID */ /* And WS 2 */ - li r10,0xf85 /* Mask to apply from PTE */ - rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */ + li r10,0xf84 /* Mask to apply from PTE */ + rlwimi r10,r12,29,30,31 /* DIRTY,READ -> SW,SR position */ and r11,r12,r10 /* Mask PTE bits to keep */ - andi. r10,r12,_PAGE_USER /* User page ? */ - beq 1f /* nope, leave U bits empty */ + bge cr7,1f /* User page ? no, leave U bits empty */ rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */ rlwinm r11,r11,0,~PPC44x_TLB_SX /* Clear SX if User page */ 1: tlbwe r11,r13,PPC44x_TLB_ATTRIB /* Write ATTRIB */ @@ -568,8 +568,8 @@ finish_tlb_load_44x: * kernel page tables. */ lis r11,PAGE_OFFSET@h - cmplw cr0,r10,r11 - blt+ 3f + cmplw cr7,r10,r11 + blt+ cr7,3f lis r11,swapper_pg_dir@h ori r11,r11, swapper_pg_dir@l li r12,0 /* MMUCR = 0 */ @@ -586,7 +586,7 @@ finish_tlb_load_44x: 4: mtspr SPRN_MMUCR,r12 /* Set MMUCR */ /* Mask of required permission bits. Note that while we - * do copy ESR:ST to _PAGE_RW position as trying to write + * do copy ESR:ST to _PAGE_WRITE position as trying to write * to an RO page is pretty common, we don't do it with * _PAGE_DIRTY. We could do it, but it's a fairly rare * event so I'd rather take the overhead when it happens @@ -599,7 +599,7 @@ finish_tlb_load_44x: * place or can we save a couple of instructions here ? */ mfspr r12,SPRN_ESR - li r13,_PAGE_PRESENT|_PAGE_ACCESSED + li r13,_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_READ rlwimi r13,r12,10,30,30 /* Load the PTE */ @@ -669,8 +669,8 @@ finish_tlb_load_44x: * kernel page tables. */ lis r11,PAGE_OFFSET@h - cmplw cr0,r10,r11 - blt+ 3f + cmplw cr7,r10,r11 + blt+ cr7,3f lis r11,swapper_pg_dir@h ori r11,r11, swapper_pg_dir@l li r12,0 /* MMUCR = 0 */ @@ -744,6 +744,7 @@ finish_tlb_load_44x: * r11 - PTE high word value * r12 - PTE low word value * r13 - free to use + * cr7 - Result of comparison with PAGE_OFFSET * MMUCR - loaded with proper value when we get here * Upon exit, we reload everything and RFI. */ @@ -753,11 +754,10 @@ finish_tlb_load_47x: tlbwe r11,r13,1 /* And make up word 2 */ - li r10,0xf85 /* Mask to apply from PTE */ - rlwimi r10,r12,29,30,30 /* DIRTY -> SW position */ + li r10,0xf84 /* Mask to apply from PTE */ + rlwimi r10,r12,29,30,31 /* DIRTY,READ -> SW,SR position */ and r11,r12,r10 /* Mask PTE bits to keep */ - andi. r10,r12,_PAGE_USER /* User page ? */ - beq 1f /* nope, leave U bits empty */ + bge cr7,1f /* User page ? no, leave U bits empty */ rlwimi r11,r11,3,26,28 /* yes, copy S bits to U */ rlwinm r11,r11,0,~PPC47x_TLB2_SX /* Clear SX if User page */ 1: tlbwe r11,r13,2 diff --git a/arch/powerpc/kernel/head_85xx.S b/arch/powerpc/kernel/head_85xx.S index 0f1641a31250..39724ff5ae1f 100644 --- a/arch/powerpc/kernel/head_85xx.S +++ b/arch/powerpc/kernel/head_85xx.S @@ -471,7 +471,7 @@ END_BTB_FLUSH_SECTION 4: /* Mask of required permission bits. Note that while we - * do copy ESR:ST to _PAGE_RW position as trying to write + * do copy ESR:ST to _PAGE_WRITE position as trying to write * to an RO page is pretty common, we don't do it with * _PAGE_DIRTY. We could do it, but it's a fairly rare * event so I'd rather take the overhead when it happens @@ -485,10 +485,10 @@ END_BTB_FLUSH_SECTION */ mfspr r12,SPRN_ESR #ifdef CONFIG_PTE_64BIT - li r13,_PAGE_PRESENT + li r13,_PAGE_PRESENT|_PAGE_BAP_SR oris r13,r13,_PAGE_ACCESSED@h #else - li r13,_PAGE_PRESENT|_PAGE_ACCESSED + li r13,_PAGE_PRESENT|_PAGE_READ|_PAGE_ACCESSED #endif rlwimi r13,r12,11,29,29 @@ -783,15 +783,15 @@ BEGIN_MMU_FTR_SECTION mtspr SPRN_MAS7, r10 END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS) #else - li r10, (_PAGE_EXEC | _PAGE_PRESENT) + li r10, (_PAGE_EXEC | _PAGE_READ) mr r13, r11 rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */ and r12, r11, r10 - andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ + mcrf cr0, cr5 /* Test for user page */ slwi r10, r12, 1 or r10, r10, r12 rlwinm r10, r10, 0, ~_PAGE_EXEC /* Clear SX on user pages */ - iseleq r12, r12, r10 + isellt r12, r10, r12 rlwimi r13, r12, 0, 20, 31 /* Get RPN from PTE, merge w/ perms */ mtspr SPRN_MAS3, r13 #endif diff --git a/arch/powerpc/kernel/head_book3s_32.S b/arch/powerpc/kernel/head_book3s_32.S index 6764b98ca360..c1d89764dd22 100644 --- a/arch/powerpc/kernel/head_book3s_32.S +++ b/arch/powerpc/kernel/head_book3s_32.S @@ -412,10 +412,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE) . = INTERRUPT_INST_TLB_MISS_603 InstructionTLBMiss: /* - * r0: scratch + * r0: userspace flag (later scratch) * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte - * r3: scratch + * r3: fault address */ /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_IMISS @@ -424,12 +424,13 @@ InstructionTLBMiss: cmplw 0,r1,r3 #endif mfspr r2, SPRN_SDR1 - li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER + li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC rlwinm r2, r2, 28, 0xfffff000 #ifdef CONFIG_MODULES + li r0, 3 bgt- 112f lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ - li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC + li r0, 0 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ #endif 112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ @@ -437,13 +438,15 @@ InstructionTLBMiss: rlwinm. r2,r2,0,0,19 /* extract address of pte page */ beq- InstructionAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - lwz r0,0(r2) /* get linux-style pte */ - andc. r1,r1,r0 /* check access & ~permission */ + lwz r2,0(r2) /* get linux-style pte */ + andc. r1,r1,r2 /* check access & ~permission */ bne- InstructionAddressInvalid /* return if access not permitted */ /* Convert linux-style PTE to low word of PPC-style PTE */ - rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */ +#ifdef CONFIG_MODULES + rlwimi r2, r0, 0, 31, 31 /* userspace ? -> PP lsb */ +#endif ori r1, r1, 0xe06 /* clear out reserved bits */ - andc r1, r0, r1 /* PP = user? 1 : 0 */ + andc r1, r2, r1 /* PP = user? 1 : 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) @@ -478,38 +481,38 @@ InstructionAddressInvalid: . = INTERRUPT_DATA_LOAD_TLB_MISS_603 DataLoadTLBMiss: /* - * r0: scratch + * r0: userspace flag (later scratch) * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte - * r3: scratch + * r3: fault address */ /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_DMISS lis r1, TASK_SIZE@h /* check if kernel address */ cmplw 0,r1,r3 mfspr r2, SPRN_SDR1 - li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER + li r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_READ rlwinm r2, r2, 28, 0xfffff000 + li r0, 3 bgt- 112f lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ - li r1, _PAGE_PRESENT | _PAGE_ACCESSED + li r0, 0 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ 112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ rlwinm. r2,r2,0,0,19 /* extract address of pte page */ beq- DataAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - lwz r0,0(r2) /* get linux-style pte */ - andc. r1,r1,r0 /* check access & ~permission */ + lwz r2,0(r2) /* get linux-style pte */ + andc. r1,r1,r2 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ /* Convert linux-style PTE to low word of PPC-style PTE */ - rlwinm r1,r0,32-9,30,30 /* _PAGE_RW -> PP msb */ - rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ - rlwimi r1,r0,32-3,24,24 /* _PAGE_RW -> _PAGE_DIRTY */ - rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */ + rlwinm r1,r2,32-9,30,30 /* _PAGE_WRITE -> PP msb */ + rlwimi r2,r0,0,30,31 /* userspace ? -> PP */ + rlwimi r1,r2,32-3,24,24 /* _PAGE_WRITE -> _PAGE_DIRTY */ xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */ ori r1,r1,0xe04 /* clear out reserved bits */ - andc r1,r0,r1 /* PP = user? rw? 1: 3: 0 */ + andc r1,r2,r1 /* PP = user? rw? 1: 3: 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) @@ -558,34 +561,35 @@ DataAddressInvalid: . = INTERRUPT_DATA_STORE_TLB_MISS_603 DataStoreTLBMiss: /* - * r0: scratch + * r0: userspace flag (later scratch) * r1: linux style pte ( later becomes ppc hardware pte ) * r2: ptr to linux-style pte - * r3: scratch + * r3: fault address */ /* Get PTE (linux-style) and check access */ mfspr r3,SPRN_DMISS lis r1, TASK_SIZE@h /* check if kernel address */ cmplw 0,r1,r3 mfspr r2, SPRN_SDR1 - li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER + li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED rlwinm r2, r2, 28, 0xfffff000 + li r0, 3 bgt- 112f lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */ - li r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED + li r0, 0 addi r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */ 112: rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ rlwinm. r2,r2,0,0,19 /* extract address of pte page */ beq- DataAddressInvalid /* return if no mapping */ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ - lwz r0,0(r2) /* get linux-style pte */ - andc. r1,r1,r0 /* check access & ~permission */ + lwz r2,0(r2) /* get linux-style pte */ + andc. r1,r1,r2 /* check access & ~permission */ bne- DataAddressInvalid /* return if access not permitted */ /* Convert linux-style PTE to low word of PPC-style PTE */ - rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */ + rlwimi r2,r0,0,31,31 /* userspace ? -> PP lsb */ li r1,0xe06 /* clear out reserved bits & PP msb */ - andc r1,r0,r1 /* PP = user? 1: 0 */ + andc r1,r2,r1 /* PP = user? 1: 0 */ BEGIN_FTR_SECTION rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) @@ -689,7 +693,8 @@ hash_page_dsi: mfdar r4 mfsrr0 r5 mfsrr1 r9 - rlwinm r3, r3, 32 - 15, _PAGE_RW /* DSISR_STORE -> _PAGE_RW */ + rlwinm r3, r3, 32 - 15, _PAGE_WRITE /* DSISR_STORE -> _PAGE_WRITE */ + ori r3, r3, _PAGE_PRESENT | _PAGE_READ bl hash_page mfspr r10, SPRN_SPRG_THREAD restore_regs_thread r10 @@ -699,7 +704,7 @@ hash_page_isi: mr r11, r10 mfspr r10, SPRN_SPRG_THREAD save_regs_thread r10 - li r3, 0 + li r3, _PAGE_PRESENT | _PAGE_EXEC lwz r4, SRR0(r10) lwz r9, SRR1(r10) bl hash_page diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index 2f29b7d432de..6af535905984 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c @@ -33,7 +33,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count) return; asm volatile("sync"); do { - tmp = *port; + tmp = *(const volatile u8 __force *)port; eieio(); *tbuf++ = tmp; } while (--count != 0); @@ -49,7 +49,7 @@ void _outsb(volatile u8 __iomem *port, const void *buf, long count) return; asm volatile("sync"); do { - *port = *tbuf++; + *(volatile u8 __force *)port = *tbuf++; } while (--count != 0); asm volatile("sync"); } @@ -64,7 +64,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) return; asm volatile("sync"); do { - tmp = *port; + tmp = *(const volatile u16 __force *)port; eieio(); *tbuf++ = tmp; } while (--count != 0); @@ -80,7 +80,7 @@ void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count) return; asm volatile("sync"); do { - *port = *tbuf++; + *(volatile u16 __force *)port = *tbuf++; } while (--count != 0); asm volatile("sync"); } @@ -95,7 +95,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) return; asm volatile("sync"); do { - tmp = *port; + tmp = *(const volatile u32 __force *)port; eieio(); *tbuf++ = tmp; } while (--count != 0); @@ -111,7 +111,7 @@ void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count) return; asm volatile("sync"); do { - *port = *tbuf++; + *(volatile u32 __force *)port = *tbuf++; } while (--count != 0); asm volatile("sync"); } diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 14251bc5219e..3e28579f7c62 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1074,10 +1074,10 @@ int iommu_tce_check_gpa(unsigned long page_shift, unsigned long gpa) } EXPORT_SYMBOL_GPL(iommu_tce_check_gpa); -extern long iommu_tce_xchg_no_kill(struct mm_struct *mm, - struct iommu_table *tbl, - unsigned long entry, unsigned long *hpa, - enum dma_data_direction *direction) +long iommu_tce_xchg_no_kill(struct mm_struct *mm, + struct iommu_table *tbl, + unsigned long entry, unsigned long *hpa, + enum dma_data_direction *direction) { long ret; unsigned long size = 0; diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index b68898ac07e1..392404688cec 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -2258,6 +2258,22 @@ unsigned long __get_wchan(struct task_struct *p) return ret; } +static bool empty_user_regs(struct pt_regs *regs, struct task_struct *tsk) +{ + unsigned long stack_page; + + // A non-empty pt_regs should never have a zero MSR or TRAP value. + if (regs->msr || regs->trap) + return false; + + // Check it sits at the very base of the stack + stack_page = (unsigned long)task_stack_page(tsk); + if ((unsigned long)(regs + 1) != stack_page + THREAD_SIZE) + return false; + + return true; +} + static int kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH; void __no_sanitize_address show_stack(struct task_struct *tsk, @@ -2322,9 +2338,13 @@ void __no_sanitize_address show_stack(struct task_struct *tsk, lr = regs->link; printk("%s--- interrupt: %lx at %pS\n", loglvl, regs->trap, (void *)regs->nip); - __show_regs(regs); - printk("%s--- interrupt: %lx\n", - loglvl, regs->trap); + + // Detect the case of an empty pt_regs at the very base + // of the stack and suppress showing it in full. + if (!empty_user_regs(regs, tsk)) { + __show_regs(regs); + printk("%s--- interrupt: %lx\n", loglvl, regs->trap); + } firstframe = 1; } diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index d464ba412084..e67effdba85c 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -947,7 +947,7 @@ struct option_vector7 { } __packed; struct ibm_arch_vec { - struct { u32 mask, val; } pvrs[14]; + struct { __be32 mask, val; } pvrs[14]; u8 num_vectors; diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c index 5d7a72b41ae7..727ed4a14545 100644 --- a/arch/powerpc/kernel/ptrace/ptrace.c +++ b/arch/powerpc/kernel/ptrace/ptrace.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -9,10 +10,6 @@ * * Modified by Cort Dougan (cort@hq.fsmlabs.com) * and Paul Mackerras (paulus@samba.org). - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file README.legal in the main directory of - * this archive for more details. */ #include diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 20f72cd1d813..ca92cf0ffde1 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -601,7 +601,6 @@ struct seq_buf ppc_hw_desc __initdata = { .buffer = ppc_hw_desc_buf, .size = sizeof(ppc_hw_desc_buf), .len = 0, - .readpos = 0, }; static __init void probe_machine(void) diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 246201d0d879..2f19d5e94485 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -364,7 +364,7 @@ void __init early_setup(unsigned long dt_ptr) */ initialise_paca(&boot_paca, 0); fixup_boot_paca(&boot_paca); - WARN_ON(local_paca != 0); + WARN_ON(local_paca); setup_paca(&boot_paca); /* install the paca into registers */ /* -------- printk is now safe to use ------- */ diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 68a91e553e14..aa17e62f3754 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Common signal handling code for both 32 and 64 bits * * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation * Extracted from signal_32.c and signal_64.c - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file README.legal in the main directory of - * this archive for more details. */ #include diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h index a429c57ed433..58ecea1cdc27 100644 --- a/arch/powerpc/kernel/signal.h +++ b/arch/powerpc/kernel/signal.h @@ -1,10 +1,7 @@ -/* +/* SPDX-License-Identifier: GPL-2.0-or-later + * * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Corporation * Extracted from signal_32.c and signal_64.c - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file README.legal in the main directory of - * this archive for more details. */ #ifndef _POWERPC_ARCH_SIGNAL_H diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 64ff37721fd0..5ea2014aff90 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -157,7 +157,7 @@ static int die_owner = -1; static unsigned int die_nest_count; static int die_counter; -extern void panic_flush_kmsg_start(void) +void panic_flush_kmsg_start(void) { /* * These are mostly taken from kernel/panic.c, but tries to do @@ -170,7 +170,7 @@ extern void panic_flush_kmsg_start(void) bust_spinlocks(1); } -extern void panic_flush_kmsg_end(void) +void panic_flush_kmsg_end(void) { kmsg_dump(KMSG_DUMP_PANIC); bust_spinlocks(0); @@ -1164,6 +1164,7 @@ void emulate_single_step(struct pt_regs *regs) __single_step_exception(regs); } +#ifdef CONFIG_PPC_FPU_REGS static inline int __parse_fpscr(unsigned long fpscr) { int ret = FPE_FLTUNK; @@ -1190,6 +1191,7 @@ static inline int __parse_fpscr(unsigned long fpscr) return ret; } +#endif static void parse_fpe(struct pt_regs *regs) { diff --git a/arch/powerpc/kexec/core.c b/arch/powerpc/kexec/core.c index 9346c960b296..85846cadb9b5 100644 --- a/arch/powerpc/kexec/core.c +++ b/arch/powerpc/kexec/core.c @@ -74,6 +74,9 @@ void arch_crash_save_vmcoreinfo(void) VMCOREINFO_STRUCT_SIZE(mmu_psize_def); VMCOREINFO_OFFSET(mmu_psize_def, shift); #endif + VMCOREINFO_SYMBOL(cur_cpu_spec); + VMCOREINFO_OFFSET(cpu_spec, mmu_features); + vmcoreinfo_append_str("NUMBER(RADIX_MMU)=%d\n", early_radix_enabled()); vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset()); } diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c index a79e28c91e2b..0bee7ca9a77c 100644 --- a/arch/powerpc/kexec/core_64.c +++ b/arch/powerpc/kexec/core_64.c @@ -379,8 +379,8 @@ void default_machine_kexec(struct kimage *image) #ifdef CONFIG_PPC_64S_HASH_MMU /* Values we need to export to the second kernel via the device tree. */ -static unsigned long htab_base; -static unsigned long htab_size; +static __be64 htab_base; +static __be64 htab_size; static struct property htab_base_prop = { .name = "linux,htab-base", diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c index a3de5369d22c..961a6dd67365 100644 --- a/arch/powerpc/kexec/file_load_64.c +++ b/arch/powerpc/kexec/file_load_64.c @@ -32,7 +32,7 @@ #include struct umem_info { - u64 *buf; /* data buffer for usable-memory property */ + __be64 *buf; /* data buffer for usable-memory property */ u32 size; /* size allocated for the data buffer */ u32 max_entries; /* maximum no. of entries */ u32 idx; /* index of current entry */ @@ -443,10 +443,10 @@ static int locate_mem_hole_bottom_up_ppc64(struct kexec_buf *kbuf, * * Returns buffer on success, NULL on error. */ -static u64 *check_realloc_usable_mem(struct umem_info *um_info, int cnt) +static __be64 *check_realloc_usable_mem(struct umem_info *um_info, int cnt) { u32 new_size; - u64 *tbuf; + __be64 *tbuf; if ((um_info->idx + cnt) <= um_info->max_entries) return um_info->buf; @@ -1138,11 +1138,15 @@ static int update_pci_dma_nodes(void *fdt, const char *dmapropname) continue; ret = copy_property(fdt, pci_offset, dn, "ibm,dma-window"); - if (ret < 0) + if (ret < 0) { + of_node_put(dn); break; + } ret = copy_property(fdt, pci_offset, dn, dmapropname); - if (ret < 0) + if (ret < 0) { + of_node_put(dn); break; + } } return ret; diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 5319d889b184..4bd9d1230869 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -87,8 +87,12 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ book3s_hv_ras.o \ book3s_hv_builtin.o \ book3s_hv_p9_perf.o \ + book3s_hv_nestedv2.o \ + guest-state-buffer.o \ $(kvm-book3s_64-builtin-tm-objs-y) \ $(kvm-book3s_64-builtin-xics-objs-y) + +obj-$(CONFIG_GUEST_STATE_BUFFER_TEST) += test-guest-state-buffer.o endif kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 686d8d9eda3e..6cd20ab9e94e 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -565,7 +565,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) regs->msr = kvmppc_get_msr(vcpu); regs->srr0 = kvmppc_get_srr0(vcpu); regs->srr1 = kvmppc_get_srr1(vcpu); - regs->pid = vcpu->arch.pid; + regs->pid = kvmppc_get_pid(vcpu); regs->sprg0 = kvmppc_get_sprg0(vcpu); regs->sprg1 = kvmppc_get_sprg1(vcpu); regs->sprg2 = kvmppc_get_sprg2(vcpu); @@ -636,17 +636,17 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, break; case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: i = id - KVM_REG_PPC_FPR0; - *val = get_reg_val(id, VCPU_FPR(vcpu, i)); + *val = get_reg_val(id, kvmppc_get_fpr(vcpu, i)); break; case KVM_REG_PPC_FPSCR: - *val = get_reg_val(id, vcpu->arch.fp.fpscr); + *val = get_reg_val(id, kvmppc_get_fpscr(vcpu)); break; #ifdef CONFIG_VSX case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: if (cpu_has_feature(CPU_FTR_VSX)) { i = id - KVM_REG_PPC_VSR0; - val->vsxval[0] = vcpu->arch.fp.fpr[i][0]; - val->vsxval[1] = vcpu->arch.fp.fpr[i][1]; + val->vsxval[0] = kvmppc_get_vsx_fpr(vcpu, i, 0); + val->vsxval[1] = kvmppc_get_vsx_fpr(vcpu, i, 1); } else { r = -ENXIO; } @@ -683,19 +683,19 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, *val = get_reg_val(id, vcpu->arch.fscr); break; case KVM_REG_PPC_TAR: - *val = get_reg_val(id, vcpu->arch.tar); + *val = get_reg_val(id, kvmppc_get_tar(vcpu)); break; case KVM_REG_PPC_EBBHR: - *val = get_reg_val(id, vcpu->arch.ebbhr); + *val = get_reg_val(id, kvmppc_get_ebbhr(vcpu)); break; case KVM_REG_PPC_EBBRR: - *val = get_reg_val(id, vcpu->arch.ebbrr); + *val = get_reg_val(id, kvmppc_get_ebbrr(vcpu)); break; case KVM_REG_PPC_BESCR: - *val = get_reg_val(id, vcpu->arch.bescr); + *val = get_reg_val(id, kvmppc_get_bescr(vcpu)); break; case KVM_REG_PPC_IC: - *val = get_reg_val(id, vcpu->arch.ic); + *val = get_reg_val(id, kvmppc_get_ic(vcpu)); break; default: r = -EINVAL; @@ -724,7 +724,7 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, break; case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: i = id - KVM_REG_PPC_FPR0; - VCPU_FPR(vcpu, i) = set_reg_val(id, *val); + kvmppc_set_fpr(vcpu, i, set_reg_val(id, *val)); break; case KVM_REG_PPC_FPSCR: vcpu->arch.fp.fpscr = set_reg_val(id, *val); @@ -733,8 +733,8 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: if (cpu_has_feature(CPU_FTR_VSX)) { i = id - KVM_REG_PPC_VSR0; - vcpu->arch.fp.fpr[i][0] = val->vsxval[0]; - vcpu->arch.fp.fpr[i][1] = val->vsxval[1]; + kvmppc_set_vsx_fpr(vcpu, i, 0, val->vsxval[0]); + kvmppc_set_vsx_fpr(vcpu, i, 1, val->vsxval[1]); } else { r = -ENXIO; } @@ -765,22 +765,22 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, break; #endif /* CONFIG_KVM_XIVE */ case KVM_REG_PPC_FSCR: - vcpu->arch.fscr = set_reg_val(id, *val); + kvmppc_set_fpscr(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_TAR: - vcpu->arch.tar = set_reg_val(id, *val); + kvmppc_set_tar(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_EBBHR: - vcpu->arch.ebbhr = set_reg_val(id, *val); + kvmppc_set_ebbhr(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_EBBRR: - vcpu->arch.ebbrr = set_reg_val(id, *val); + kvmppc_set_ebbrr(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_BESCR: - vcpu->arch.bescr = set_reg_val(id, *val); + kvmppc_set_bescr(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_IC: - vcpu->arch.ic = set_reg_val(id, *val); + kvmppc_set_ic(vcpu, set_reg_val(id, *val)); break; default: r = -EINVAL; diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index efd0ebf70a5e..2b1f0cdd8c18 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -28,6 +28,7 @@ #include #include "book3s.h" +#include "book3s_hv.h" #include "trace_hv.h" //#define DEBUG_RESIZE_HPT 1 @@ -120,7 +121,7 @@ void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info) kvm->arch.hpt = *info; kvm->arch.sdr1 = __pa(info->virt) | (info->order - 18); - pr_debug("KVM guest htab at %lx (order %ld), LPID %x\n", + pr_debug("KVM guest htab at %lx (order %ld), LPID %llx\n", info->virt, (long)info->order, kvm->arch.lpid); } @@ -347,7 +348,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned long v, orig_v, gr; __be64 *hptep; long int index; - int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR); + int virtmode = __kvmppc_get_msr_hv(vcpu) & (data ? MSR_DR : MSR_IR); if (kvm_is_radix(vcpu->kvm)) return kvmppc_mmu_radix_xlate(vcpu, eaddr, gpte, data, iswrite); @@ -385,7 +386,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, /* Get PP bits and key for permission check */ pp = gr & (HPTE_R_PP0 | HPTE_R_PP); - key = (vcpu->arch.shregs.msr & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS; + key = (__kvmppc_get_msr_hv(vcpu) & MSR_PR) ? SLB_VSID_KP : SLB_VSID_KS; key &= slb_v; /* Calculate permissions */ diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 572707858d65..175a8eb2681f 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -15,6 +15,7 @@ #include #include +#include "book3s_hv.h" #include #include #include @@ -96,7 +97,7 @@ static long kvmhv_copy_tofrom_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, void *to, void *from, unsigned long n) { int lpid = vcpu->kvm->arch.lpid; - int pid = vcpu->arch.pid; + int pid = kvmppc_get_pid(vcpu); /* This would cause a data segment intr so don't allow the access */ if (eaddr & (0x3FFUL << 52)) @@ -270,7 +271,7 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, /* Work out effective PID */ switch (eaddr >> 62) { case 0: - pid = vcpu->arch.pid; + pid = kvmppc_get_pid(vcpu); break; case 3: pid = 0; @@ -294,9 +295,9 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, } else { if (!(pte & _PAGE_PRIVILEGED)) { /* Check AMR/IAMR to see if strict mode is in force */ - if (vcpu->arch.amr & (1ul << 62)) + if (kvmppc_get_amr_hv(vcpu) & (1ul << 62)) gpte->may_read = 0; - if (vcpu->arch.amr & (1ul << 63)) + if (kvmppc_get_amr_hv(vcpu) & (1ul << 63)) gpte->may_write = 0; if (vcpu->arch.iamr & (1ul << 62)) gpte->may_execute = 0; @@ -307,7 +308,7 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, } void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr, - unsigned int pshift, unsigned int lpid) + unsigned int pshift, u64 lpid) { unsigned long psize = PAGE_SIZE; int psi; @@ -344,7 +345,7 @@ void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr, pr_err("KVM: TLB page invalidation hcall failed, rc=%ld\n", rc); } -static void kvmppc_radix_flush_pwc(struct kvm *kvm, unsigned int lpid) +static void kvmppc_radix_flush_pwc(struct kvm *kvm, u64 lpid) { long rc; @@ -417,7 +418,7 @@ static void kvmppc_pmd_free(pmd_t *pmdp) void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, unsigned int shift, const struct kvm_memory_slot *memslot, - unsigned int lpid) + u64 lpid) { unsigned long old; @@ -468,7 +469,7 @@ void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, * (or 4kB) mappings (of sub-pages of the same 2MB page). */ static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full, - unsigned int lpid) + u64 lpid) { if (full) { memset(pte, 0, sizeof(long) << RADIX_PTE_INDEX_SIZE); @@ -489,7 +490,7 @@ static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full, } static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full, - unsigned int lpid) + u64 lpid) { unsigned long im; pmd_t *p = pmd; @@ -518,7 +519,7 @@ static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full, } static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud, - unsigned int lpid) + u64 lpid) { unsigned long iu; pud_t *p = pud; @@ -539,7 +540,7 @@ static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud, pud_free(kvm->mm, pud); } -void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, unsigned int lpid) +void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, u64 lpid) { unsigned long ig; @@ -566,7 +567,7 @@ void kvmppc_free_radix(struct kvm *kvm) } static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd, - unsigned long gpa, unsigned int lpid) + unsigned long gpa, u64 lpid) { pte_t *pte = pte_offset_kernel(pmd, 0); @@ -582,7 +583,7 @@ static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd, } static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud, - unsigned long gpa, unsigned int lpid) + unsigned long gpa, u64 lpid) { pmd_t *pmd = pmd_offset(pud, 0); @@ -608,7 +609,7 @@ static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud, int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte, unsigned long gpa, unsigned int level, - unsigned long mmu_seq, unsigned int lpid, + unsigned long mmu_seq, u64 lpid, unsigned long *rmapp, struct rmap_nested **n_rmap) { pgd_t *pgd; @@ -785,7 +786,7 @@ int kvmppc_create_pte(struct kvm *kvm, pgd_t *pgtable, pte_t pte, } bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested, bool writing, - unsigned long gpa, unsigned int lpid) + unsigned long gpa, u64 lpid) { unsigned long pgflags; unsigned int shift; diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 93b695b289e9..14c6d7e318da 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c @@ -77,8 +77,8 @@ static void kvm_spapr_tce_liobn_put(struct kref *kref) call_rcu(&stit->rcu, kvm_spapr_tce_iommu_table_free); } -extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm, - struct iommu_group *grp) +void kvm_spapr_tce_release_iommu_group(struct kvm *kvm, + struct iommu_group *grp) { int i; struct kvmppc_spapr_tce_table *stt; @@ -105,8 +105,8 @@ extern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm, rcu_read_unlock(); } -extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, - struct iommu_group *grp) +long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd, + struct iommu_group *grp) { struct kvmppc_spapr_tce_table *stt = NULL; bool found = false; @@ -786,12 +786,12 @@ long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, idx = (ioba >> stt->page_shift) - stt->offset; page = stt->pages[idx / TCES_PER_PAGE]; if (!page) { - vcpu->arch.regs.gpr[4] = 0; + kvmppc_set_gpr(vcpu, 4, 0); return H_SUCCESS; } tbl = (u64 *)page_address(page); - vcpu->arch.regs.gpr[4] = tbl[idx % TCES_PER_PAGE]; + kvmppc_set_gpr(vcpu, 4, tbl[idx % TCES_PER_PAGE]); return H_SUCCESS; } diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 130bafdb1430..1ed6ec140701 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -393,7 +393,7 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr) static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) { - unsigned long host_pcr_bit = 0, guest_pcr_bit = 0; + unsigned long host_pcr_bit = 0, guest_pcr_bit = 0, cap = 0; struct kvmppc_vcore *vc = vcpu->arch.vcore; /* We can (emulate) our own architecture version and anything older */ @@ -424,9 +424,11 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) break; case PVR_ARCH_300: guest_pcr_bit = PCR_ARCH_300; + cap = H_GUEST_CAP_POWER9; break; case PVR_ARCH_31: guest_pcr_bit = PCR_ARCH_31; + cap = H_GUEST_CAP_POWER10; break; default: return -EINVAL; @@ -437,8 +439,14 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) if (guest_pcr_bit > host_pcr_bit) return -EINVAL; + if (kvmhv_on_pseries() && kvmhv_is_nestedv2()) { + if (!(cap & nested_capabilities)) + return -EINVAL; + } + spin_lock(&vc->lock); vc->arch_compat = arch_compat; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LOGICAL_PVR); /* * Set all PCR bits for which guest_pcr_bit <= bit < host_pcr_bit * Also set all reserved PCR bits @@ -794,7 +802,7 @@ static void kvmppc_update_vpa_dispatch(struct kvm_vcpu *vcpu, vpa->enqueue_dispatch_tb = cpu_to_be64(be64_to_cpu(vpa->enqueue_dispatch_tb) + stolen); - __kvmppc_create_dtl_entry(vcpu, vpa, vc->pcpu, now + vc->tb_offset, stolen); + __kvmppc_create_dtl_entry(vcpu, vpa, vc->pcpu, now + kvmppc_get_tb_offset(vcpu), stolen); vcpu->arch.vpa.dirty = true; } @@ -845,9 +853,9 @@ static bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu) static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu) { - if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207) + if (kvmppc_get_arch_compat(vcpu) >= PVR_ARCH_207) return true; - if ((!vcpu->arch.vcore->arch_compat) && + if ((!kvmppc_get_arch_compat(vcpu)) && cpu_has_feature(CPU_FTR_ARCH_207S)) return true; return false; @@ -868,7 +876,7 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, /* Guests can't breakpoint the hypervisor */ if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER) return H_P3; - vcpu->arch.ciabr = value1; + kvmppc_set_ciabr_hv(vcpu, value1); return H_SUCCESS; case H_SET_MODE_RESOURCE_SET_DAWR0: if (!kvmppc_power8_compatible(vcpu)) @@ -879,8 +887,8 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, return H_UNSUPPORTED_FLAG_START; if (value2 & DABRX_HYP) return H_P4; - vcpu->arch.dawr0 = value1; - vcpu->arch.dawrx0 = value2; + kvmppc_set_dawr0_hv(vcpu, value1); + kvmppc_set_dawrx0_hv(vcpu, value2); return H_SUCCESS; case H_SET_MODE_RESOURCE_SET_DAWR1: if (!kvmppc_power8_compatible(vcpu)) @@ -895,8 +903,8 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, return H_UNSUPPORTED_FLAG_START; if (value2 & DABRX_HYP) return H_P4; - vcpu->arch.dawr1 = value1; - vcpu->arch.dawrx1 = value2; + kvmppc_set_dawr1_hv(vcpu, value1); + kvmppc_set_dawrx1_hv(vcpu, value2); return H_SUCCESS; case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE: /* @@ -1267,10 +1275,14 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) return RESUME_HOST; break; #endif - case H_RANDOM: - if (!arch_get_random_seed_longs(&vcpu->arch.regs.gpr[4], 1)) + case H_RANDOM: { + unsigned long rand; + + if (!arch_get_random_seed_longs(&rand, 1)) ret = H_HARDWARE; + kvmppc_set_gpr(vcpu, 4, rand); break; + } case H_RPT_INVALIDATE: ret = kvmppc_h_rpt_invalidate(vcpu, kvmppc_get_gpr(vcpu, 4), kvmppc_get_gpr(vcpu, 5), @@ -1370,7 +1382,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) */ static void kvmppc_cede(struct kvm_vcpu *vcpu) { - vcpu->arch.shregs.msr |= MSR_EE; + __kvmppc_set_msr_hv(vcpu, __kvmppc_get_msr_hv(vcpu) | MSR_EE); vcpu->arch.ceded = 1; smp_mb(); if (vcpu->arch.prodded) { @@ -1544,7 +1556,7 @@ static int kvmppc_pmu_unavailable(struct kvm_vcpu *vcpu) if (!(vcpu->arch.hfscr_permitted & HFSCR_PM)) return EMULATE_FAIL; - vcpu->arch.hfscr |= HFSCR_PM; + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_PM); return RESUME_GUEST; } @@ -1554,7 +1566,7 @@ static int kvmppc_ebb_unavailable(struct kvm_vcpu *vcpu) if (!(vcpu->arch.hfscr_permitted & HFSCR_EBB)) return EMULATE_FAIL; - vcpu->arch.hfscr |= HFSCR_EBB; + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_EBB); return RESUME_GUEST; } @@ -1564,7 +1576,7 @@ static int kvmppc_tm_unavailable(struct kvm_vcpu *vcpu) if (!(vcpu->arch.hfscr_permitted & HFSCR_TM)) return EMULATE_FAIL; - vcpu->arch.hfscr |= HFSCR_TM; + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_TM); return RESUME_GUEST; } @@ -1585,7 +1597,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, * That can happen due to a bug, or due to a machine check * occurring at just the wrong time. */ - if (vcpu->arch.shregs.msr & MSR_HV) { + if (__kvmppc_get_msr_hv(vcpu) & MSR_HV) { printk(KERN_EMERG "KVM trap in HV mode!\n"); printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n", vcpu->arch.trap, kvmppc_get_pc(vcpu), @@ -1636,7 +1648,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, * so that it knows that the machine check occurred. */ if (!vcpu->kvm->arch.fwnmi_enabled) { - ulong flags = (vcpu->arch.shregs.msr & 0x083c0000) | + ulong flags = (__kvmppc_get_msr_hv(vcpu) & 0x083c0000) | (kvmppc_get_msr(vcpu) & SRR1_PREFIXED); kvmppc_core_queue_machine_check(vcpu, flags); r = RESUME_GUEST; @@ -1666,7 +1678,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, * as a result of a hypervisor emulation interrupt * (e40) getting turned into a 700 by BML RTAS. */ - flags = (vcpu->arch.shregs.msr & 0x1f0000ull) | + flags = (__kvmppc_get_msr_hv(vcpu) & 0x1f0000ull) | (kvmppc_get_msr(vcpu) & SRR1_PREFIXED); kvmppc_core_queue_program(vcpu, flags); r = RESUME_GUEST; @@ -1676,7 +1688,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, { int i; - if (unlikely(vcpu->arch.shregs.msr & MSR_PR)) { + if (unlikely(__kvmppc_get_msr_hv(vcpu) & MSR_PR)) { /* * Guest userspace executed sc 1. This can only be * reached by the P9 path because the old path @@ -1754,7 +1766,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, break; } - if (!(vcpu->arch.shregs.msr & MSR_DR)) + if (!(__kvmppc_get_msr_hv(vcpu) & MSR_DR)) vsid = vcpu->kvm->arch.vrma_slb_v; else vsid = vcpu->arch.fault_gpa; @@ -1778,7 +1790,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, long err; vcpu->arch.fault_dar = kvmppc_get_pc(vcpu); - vcpu->arch.fault_dsisr = vcpu->arch.shregs.msr & + vcpu->arch.fault_dsisr = __kvmppc_get_msr_hv(vcpu) & DSISR_SRR1_MATCH_64S; if (kvm_is_radix(vcpu->kvm) || !cpu_has_feature(CPU_FTR_ARCH_300)) { /* @@ -1787,7 +1799,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, * hash fault handling below is v3 only (it uses ASDR * via fault_gpa). */ - if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE) + if (__kvmppc_get_msr_hv(vcpu) & HSRR1_HISI_WRITE) vcpu->arch.fault_dsisr |= DSISR_ISSTORE; r = RESUME_PAGE_FAULT; break; @@ -1801,7 +1813,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, break; } - if (!(vcpu->arch.shregs.msr & MSR_IR)) + if (!(__kvmppc_get_msr_hv(vcpu) & MSR_IR)) vsid = vcpu->kvm->arch.vrma_slb_v; else vsid = vcpu->arch.fault_gpa; @@ -1863,7 +1875,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, * Otherwise, we just generate a program interrupt to the guest. */ case BOOK3S_INTERRUPT_H_FAC_UNAVAIL: { - u64 cause = vcpu->arch.hfscr >> 56; + u64 cause = kvmppc_get_hfscr_hv(vcpu) >> 56; r = EMULATE_FAIL; if (cpu_has_feature(CPU_FTR_ARCH_300)) { @@ -1891,7 +1903,7 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu, kvmppc_dump_regs(vcpu); printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n", vcpu->arch.trap, kvmppc_get_pc(vcpu), - vcpu->arch.shregs.msr); + __kvmppc_get_msr_hv(vcpu)); run->hw.hardware_exit_reason = vcpu->arch.trap; r = RESUME_HOST; break; @@ -1915,11 +1927,11 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) * That can happen due to a bug, or due to a machine check * occurring at just the wrong time. */ - if (vcpu->arch.shregs.msr & MSR_HV) { + if (__kvmppc_get_msr_hv(vcpu) & MSR_HV) { pr_emerg("KVM trap in HV mode while nested!\n"); pr_emerg("trap=0x%x | pc=0x%lx | msr=0x%llx\n", vcpu->arch.trap, kvmppc_get_pc(vcpu), - vcpu->arch.shregs.msr); + __kvmppc_get_msr_hv(vcpu)); kvmppc_dump_regs(vcpu); return RESUME_HOST; } @@ -1976,7 +1988,7 @@ static int kvmppc_handle_nested_exit(struct kvm_vcpu *vcpu) vcpu->arch.fault_dar = kvmppc_get_pc(vcpu); vcpu->arch.fault_dsisr = kvmppc_get_msr(vcpu) & DSISR_SRR1_MATCH_64S; - if (vcpu->arch.shregs.msr & HSRR1_HISI_WRITE) + if (__kvmppc_get_msr_hv(vcpu) & HSRR1_HISI_WRITE) vcpu->arch.fault_dsisr |= DSISR_ISSTORE; srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); r = kvmhv_nested_page_fault(vcpu); @@ -2183,6 +2195,7 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, } vc->lpcr = new_lpcr; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LPCR); spin_unlock(&vc->lock); } @@ -2207,64 +2220,64 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, *val = get_reg_val(id, vcpu->arch.dabrx); break; case KVM_REG_PPC_DSCR: - *val = get_reg_val(id, vcpu->arch.dscr); + *val = get_reg_val(id, kvmppc_get_dscr_hv(vcpu)); break; case KVM_REG_PPC_PURR: - *val = get_reg_val(id, vcpu->arch.purr); + *val = get_reg_val(id, kvmppc_get_purr_hv(vcpu)); break; case KVM_REG_PPC_SPURR: - *val = get_reg_val(id, vcpu->arch.spurr); + *val = get_reg_val(id, kvmppc_get_spurr_hv(vcpu)); break; case KVM_REG_PPC_AMR: - *val = get_reg_val(id, vcpu->arch.amr); + *val = get_reg_val(id, kvmppc_get_amr_hv(vcpu)); break; case KVM_REG_PPC_UAMOR: - *val = get_reg_val(id, vcpu->arch.uamor); + *val = get_reg_val(id, kvmppc_get_uamor_hv(vcpu)); break; case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCR1: i = id - KVM_REG_PPC_MMCR0; - *val = get_reg_val(id, vcpu->arch.mmcr[i]); + *val = get_reg_val(id, kvmppc_get_mmcr_hv(vcpu, i)); break; case KVM_REG_PPC_MMCR2: - *val = get_reg_val(id, vcpu->arch.mmcr[2]); + *val = get_reg_val(id, kvmppc_get_mmcr_hv(vcpu, 2)); break; case KVM_REG_PPC_MMCRA: - *val = get_reg_val(id, vcpu->arch.mmcra); + *val = get_reg_val(id, kvmppc_get_mmcra_hv(vcpu)); break; case KVM_REG_PPC_MMCRS: *val = get_reg_val(id, vcpu->arch.mmcrs); break; case KVM_REG_PPC_MMCR3: - *val = get_reg_val(id, vcpu->arch.mmcr[3]); + *val = get_reg_val(id, kvmppc_get_mmcr_hv(vcpu, 3)); break; case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8: i = id - KVM_REG_PPC_PMC1; - *val = get_reg_val(id, vcpu->arch.pmc[i]); + *val = get_reg_val(id, kvmppc_get_pmc_hv(vcpu, i)); break; case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2: i = id - KVM_REG_PPC_SPMC1; *val = get_reg_val(id, vcpu->arch.spmc[i]); break; case KVM_REG_PPC_SIAR: - *val = get_reg_val(id, vcpu->arch.siar); + *val = get_reg_val(id, kvmppc_get_siar_hv(vcpu)); break; case KVM_REG_PPC_SDAR: - *val = get_reg_val(id, vcpu->arch.sdar); + *val = get_reg_val(id, kvmppc_get_siar_hv(vcpu)); break; case KVM_REG_PPC_SIER: - *val = get_reg_val(id, vcpu->arch.sier[0]); + *val = get_reg_val(id, kvmppc_get_sier_hv(vcpu, 0)); break; case KVM_REG_PPC_SIER2: - *val = get_reg_val(id, vcpu->arch.sier[1]); + *val = get_reg_val(id, kvmppc_get_sier_hv(vcpu, 1)); break; case KVM_REG_PPC_SIER3: - *val = get_reg_val(id, vcpu->arch.sier[2]); + *val = get_reg_val(id, kvmppc_get_sier_hv(vcpu, 2)); break; case KVM_REG_PPC_IAMR: - *val = get_reg_val(id, vcpu->arch.iamr); + *val = get_reg_val(id, kvmppc_get_iamr_hv(vcpu)); break; case KVM_REG_PPC_PSPB: - *val = get_reg_val(id, vcpu->arch.pspb); + *val = get_reg_val(id, kvmppc_get_pspb_hv(vcpu)); break; case KVM_REG_PPC_DPDES: /* @@ -2279,22 +2292,22 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, *val = get_reg_val(id, vcpu->arch.vcore->dpdes); break; case KVM_REG_PPC_VTB: - *val = get_reg_val(id, vcpu->arch.vcore->vtb); + *val = get_reg_val(id, kvmppc_get_vtb(vcpu)); break; case KVM_REG_PPC_DAWR: - *val = get_reg_val(id, vcpu->arch.dawr0); + *val = get_reg_val(id, kvmppc_get_dawr0_hv(vcpu)); break; case KVM_REG_PPC_DAWRX: - *val = get_reg_val(id, vcpu->arch.dawrx0); + *val = get_reg_val(id, kvmppc_get_dawrx0_hv(vcpu)); break; case KVM_REG_PPC_DAWR1: - *val = get_reg_val(id, vcpu->arch.dawr1); + *val = get_reg_val(id, kvmppc_get_dawr1_hv(vcpu)); break; case KVM_REG_PPC_DAWRX1: - *val = get_reg_val(id, vcpu->arch.dawrx1); + *val = get_reg_val(id, kvmppc_get_dawrx1_hv(vcpu)); break; case KVM_REG_PPC_CIABR: - *val = get_reg_val(id, vcpu->arch.ciabr); + *val = get_reg_val(id, kvmppc_get_ciabr_hv(vcpu)); break; case KVM_REG_PPC_CSIGR: *val = get_reg_val(id, vcpu->arch.csigr); @@ -2306,13 +2319,13 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, *val = get_reg_val(id, vcpu->arch.tcscr); break; case KVM_REG_PPC_PID: - *val = get_reg_val(id, vcpu->arch.pid); + *val = get_reg_val(id, kvmppc_get_pid(vcpu)); break; case KVM_REG_PPC_ACOP: *val = get_reg_val(id, vcpu->arch.acop); break; case KVM_REG_PPC_WORT: - *val = get_reg_val(id, vcpu->arch.wort); + *val = get_reg_val(id, kvmppc_get_wort_hv(vcpu)); break; case KVM_REG_PPC_TIDR: *val = get_reg_val(id, vcpu->arch.tid); @@ -2338,14 +2351,14 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, spin_unlock(&vcpu->arch.vpa_update_lock); break; case KVM_REG_PPC_TB_OFFSET: - *val = get_reg_val(id, vcpu->arch.vcore->tb_offset); + *val = get_reg_val(id, kvmppc_get_tb_offset(vcpu)); break; case KVM_REG_PPC_LPCR: case KVM_REG_PPC_LPCR_64: - *val = get_reg_val(id, vcpu->arch.vcore->lpcr); + *val = get_reg_val(id, kvmppc_get_lpcr(vcpu)); break; case KVM_REG_PPC_PPR: - *val = get_reg_val(id, vcpu->arch.ppr); + *val = get_reg_val(id, kvmppc_get_ppr_hv(vcpu)); break; #ifdef CONFIG_PPC_TRANSACTIONAL_MEM case KVM_REG_PPC_TFHAR: @@ -2414,10 +2427,10 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, break; #endif case KVM_REG_PPC_ARCH_COMPAT: - *val = get_reg_val(id, vcpu->arch.vcore->arch_compat); + *val = get_reg_val(id, kvmppc_get_arch_compat(vcpu)); break; case KVM_REG_PPC_DEC_EXPIRY: - *val = get_reg_val(id, vcpu->arch.dec_expires); + *val = get_reg_val(id, kvmppc_get_dec_expires(vcpu)); break; case KVM_REG_PPC_ONLINE: *val = get_reg_val(id, vcpu->arch.online); @@ -2425,6 +2438,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_PTCR: *val = get_reg_val(id, vcpu->kvm->arch.l1_ptcr); break; + case KVM_REG_PPC_FSCR: + *val = get_reg_val(id, kvmppc_get_fscr_hv(vcpu)); + break; default: r = -EINVAL; break; @@ -2453,29 +2469,29 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, vcpu->arch.dabrx = set_reg_val(id, *val) & ~DABRX_HYP; break; case KVM_REG_PPC_DSCR: - vcpu->arch.dscr = set_reg_val(id, *val); + kvmppc_set_dscr_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_PURR: - vcpu->arch.purr = set_reg_val(id, *val); + kvmppc_set_purr_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_SPURR: - vcpu->arch.spurr = set_reg_val(id, *val); + kvmppc_set_spurr_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_AMR: - vcpu->arch.amr = set_reg_val(id, *val); + kvmppc_set_amr_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_UAMOR: - vcpu->arch.uamor = set_reg_val(id, *val); + kvmppc_set_uamor_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_MMCR0 ... KVM_REG_PPC_MMCR1: i = id - KVM_REG_PPC_MMCR0; - vcpu->arch.mmcr[i] = set_reg_val(id, *val); + kvmppc_set_mmcr_hv(vcpu, i, set_reg_val(id, *val)); break; case KVM_REG_PPC_MMCR2: - vcpu->arch.mmcr[2] = set_reg_val(id, *val); + kvmppc_set_mmcr_hv(vcpu, 2, set_reg_val(id, *val)); break; case KVM_REG_PPC_MMCRA: - vcpu->arch.mmcra = set_reg_val(id, *val); + kvmppc_set_mmcra_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_MMCRS: vcpu->arch.mmcrs = set_reg_val(id, *val); @@ -2485,32 +2501,32 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, break; case KVM_REG_PPC_PMC1 ... KVM_REG_PPC_PMC8: i = id - KVM_REG_PPC_PMC1; - vcpu->arch.pmc[i] = set_reg_val(id, *val); + kvmppc_set_pmc_hv(vcpu, i, set_reg_val(id, *val)); break; case KVM_REG_PPC_SPMC1 ... KVM_REG_PPC_SPMC2: i = id - KVM_REG_PPC_SPMC1; vcpu->arch.spmc[i] = set_reg_val(id, *val); break; case KVM_REG_PPC_SIAR: - vcpu->arch.siar = set_reg_val(id, *val); + kvmppc_set_siar_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_SDAR: - vcpu->arch.sdar = set_reg_val(id, *val); + kvmppc_set_sdar_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_SIER: - vcpu->arch.sier[0] = set_reg_val(id, *val); + kvmppc_set_sier_hv(vcpu, 0, set_reg_val(id, *val)); break; case KVM_REG_PPC_SIER2: - vcpu->arch.sier[1] = set_reg_val(id, *val); + kvmppc_set_sier_hv(vcpu, 1, set_reg_val(id, *val)); break; case KVM_REG_PPC_SIER3: - vcpu->arch.sier[2] = set_reg_val(id, *val); + kvmppc_set_sier_hv(vcpu, 2, set_reg_val(id, *val)); break; case KVM_REG_PPC_IAMR: - vcpu->arch.iamr = set_reg_val(id, *val); + kvmppc_set_iamr_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_PSPB: - vcpu->arch.pspb = set_reg_val(id, *val); + kvmppc_set_pspb_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_DPDES: if (cpu_has_feature(CPU_FTR_ARCH_300)) @@ -2519,25 +2535,25 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, vcpu->arch.vcore->dpdes = set_reg_val(id, *val); break; case KVM_REG_PPC_VTB: - vcpu->arch.vcore->vtb = set_reg_val(id, *val); + kvmppc_set_vtb(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_DAWR: - vcpu->arch.dawr0 = set_reg_val(id, *val); + kvmppc_set_dawr0_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_DAWRX: - vcpu->arch.dawrx0 = set_reg_val(id, *val) & ~DAWRX_HYP; + kvmppc_set_dawrx0_hv(vcpu, set_reg_val(id, *val) & ~DAWRX_HYP); break; case KVM_REG_PPC_DAWR1: - vcpu->arch.dawr1 = set_reg_val(id, *val); + kvmppc_set_dawr1_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_DAWRX1: - vcpu->arch.dawrx1 = set_reg_val(id, *val) & ~DAWRX_HYP; + kvmppc_set_dawrx1_hv(vcpu, set_reg_val(id, *val) & ~DAWRX_HYP); break; case KVM_REG_PPC_CIABR: - vcpu->arch.ciabr = set_reg_val(id, *val); + kvmppc_set_ciabr_hv(vcpu, set_reg_val(id, *val)); /* Don't allow setting breakpoints in hypervisor code */ - if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER) - vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */ + if ((kvmppc_get_ciabr_hv(vcpu) & CIABR_PRIV) == CIABR_PRIV_HYPER) + kvmppc_set_ciabr_hv(vcpu, kvmppc_get_ciabr_hv(vcpu) & ~CIABR_PRIV); break; case KVM_REG_PPC_CSIGR: vcpu->arch.csigr = set_reg_val(id, *val); @@ -2549,13 +2565,13 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, vcpu->arch.tcscr = set_reg_val(id, *val); break; case KVM_REG_PPC_PID: - vcpu->arch.pid = set_reg_val(id, *val); + kvmppc_set_pid(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_ACOP: vcpu->arch.acop = set_reg_val(id, *val); break; case KVM_REG_PPC_WORT: - vcpu->arch.wort = set_reg_val(id, *val); + kvmppc_set_wort_hv(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_TIDR: vcpu->arch.tid = set_reg_val(id, *val); @@ -2602,10 +2618,11 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, * decrementer, which is better than a large one that * causes a hang. */ - if (!vcpu->arch.dec_expires && tb_offset) - vcpu->arch.dec_expires = get_tb() + tb_offset; + kvmppc_set_tb_offset(vcpu, tb_offset); + if (!kvmppc_get_dec_expires(vcpu) && tb_offset) + kvmppc_set_dec_expires(vcpu, get_tb() + tb_offset); - vcpu->arch.vcore->tb_offset = tb_offset; + kvmppc_set_tb_offset(vcpu, tb_offset); break; } case KVM_REG_PPC_LPCR: @@ -2615,7 +2632,7 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false); break; case KVM_REG_PPC_PPR: - vcpu->arch.ppr = set_reg_val(id, *val); + kvmppc_set_ppr_hv(vcpu, set_reg_val(id, *val)); break; #ifdef CONFIG_PPC_TRANSACTIONAL_MEM case KVM_REG_PPC_TFHAR: @@ -2686,7 +2703,7 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_DEC_EXPIRY: - vcpu->arch.dec_expires = set_reg_val(id, *val); + kvmppc_set_dec_expires(vcpu, set_reg_val(id, *val)); break; case KVM_REG_PPC_ONLINE: i = set_reg_val(id, *val); @@ -2699,6 +2716,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, case KVM_REG_PPC_PTCR: vcpu->kvm->arch.l1_ptcr = set_reg_val(id, *val); break; + case KVM_REG_PPC_FSCR: + kvmppc_set_fscr_hv(vcpu, set_reg_val(id, *val)); + break; default: r = -EINVAL; break; @@ -2916,19 +2936,26 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu) vcpu->arch.shared_big_endian = false; #endif #endif - vcpu->arch.mmcr[0] = MMCR0_FC; - if (cpu_has_feature(CPU_FTR_ARCH_31)) { - vcpu->arch.mmcr[0] |= MMCR0_PMCCEXT; - vcpu->arch.mmcra = MMCRA_BHRB_DISABLE; + + if (kvmhv_is_nestedv2()) { + err = kvmhv_nestedv2_vcpu_create(vcpu, &vcpu->arch.nestedv2_io); + if (err < 0) + return err; } - vcpu->arch.ctrl = CTRL_RUNLATCH; + kvmppc_set_mmcr_hv(vcpu, 0, MMCR0_FC); + if (cpu_has_feature(CPU_FTR_ARCH_31)) { + kvmppc_set_mmcr_hv(vcpu, 0, kvmppc_get_mmcr_hv(vcpu, 0) | MMCR0_PMCCEXT); + kvmppc_set_mmcra_hv(vcpu, MMCRA_BHRB_DISABLE); + } + + kvmppc_set_ctrl_hv(vcpu, CTRL_RUNLATCH); /* default to host PVR, since we can't spoof it */ kvmppc_set_pvr_hv(vcpu, mfspr(SPRN_PVR)); spin_lock_init(&vcpu->arch.vpa_update_lock); spin_lock_init(&vcpu->arch.tbacct_lock); vcpu->arch.busy_preempt = TB_NIL; - vcpu->arch.shregs.msr = MSR_ME; + __kvmppc_set_msr_hv(vcpu, MSR_ME); vcpu->arch.intr_msr = MSR_SF | MSR_ME; /* @@ -2938,29 +2965,30 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu *vcpu) * don't set the HFSCR_MSGP bit, and that causes those instructions * to trap and then we emulate them. */ - vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB | - HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP; + kvmppc_set_hfscr_hv(vcpu, HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB | + HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP); /* On POWER10 and later, allow prefixed instructions */ if (cpu_has_feature(CPU_FTR_ARCH_31)) - vcpu->arch.hfscr |= HFSCR_PREFIX; + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_PREFIX); if (cpu_has_feature(CPU_FTR_HVMODE)) { - vcpu->arch.hfscr &= mfspr(SPRN_HFSCR); + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) & mfspr(SPRN_HFSCR)); + #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) - vcpu->arch.hfscr |= HFSCR_TM; + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) | HFSCR_TM); #endif } if (cpu_has_feature(CPU_FTR_TM_COMP)) vcpu->arch.hfscr |= HFSCR_TM; - vcpu->arch.hfscr_permitted = vcpu->arch.hfscr; + vcpu->arch.hfscr_permitted = kvmppc_get_hfscr_hv(vcpu); /* * PM, EBB, TM are demand-faulted so start with it clear. */ - vcpu->arch.hfscr &= ~(HFSCR_PM | HFSCR_EBB | HFSCR_TM); + kvmppc_set_hfscr_hv(vcpu, kvmppc_get_hfscr_hv(vcpu) & ~(HFSCR_PM | HFSCR_EBB | HFSCR_TM)); kvmppc_mmu_book3s_hv_init(vcpu); @@ -3071,6 +3099,8 @@ static void kvmppc_core_vcpu_free_hv(struct kvm_vcpu *vcpu) unpin_vpa(vcpu->kvm, &vcpu->arch.slb_shadow); unpin_vpa(vcpu->kvm, &vcpu->arch.vpa); spin_unlock(&vcpu->arch.vpa_update_lock); + if (kvmhv_is_nestedv2()) + kvmhv_nestedv2_vcpu_free(vcpu, &vcpu->arch.nestedv2_io); } static int kvmppc_core_check_requests_hv(struct kvm_vcpu *vcpu) @@ -4035,10 +4065,58 @@ static void vcpu_vpa_increment_dispatch(struct kvm_vcpu *vcpu) } } +static int kvmhv_vcpu_entry_nestedv2(struct kvm_vcpu *vcpu, u64 time_limit, + unsigned long lpcr, u64 *tb) +{ + struct kvmhv_nestedv2_io *io; + unsigned long msr, i; + int trap; + long rc; + + io = &vcpu->arch.nestedv2_io; + + msr = mfmsr(); + kvmppc_msr_hard_disable_set_facilities(vcpu, msr); + if (lazy_irq_pending()) + return 0; + + rc = kvmhv_nestedv2_flush_vcpu(vcpu, time_limit); + if (rc < 0) + return -EINVAL; + + accumulate_time(vcpu, &vcpu->arch.in_guest); + rc = plpar_guest_run_vcpu(0, vcpu->kvm->arch.lpid, vcpu->vcpu_id, + &trap, &i); + + if (rc != H_SUCCESS) { + pr_err("KVM Guest Run VCPU hcall failed\n"); + if (rc == H_INVALID_ELEMENT_ID) + pr_err("KVM: Guest Run VCPU invalid element id at %ld\n", i); + else if (rc == H_INVALID_ELEMENT_SIZE) + pr_err("KVM: Guest Run VCPU invalid element size at %ld\n", i); + else if (rc == H_INVALID_ELEMENT_VALUE) + pr_err("KVM: Guest Run VCPU invalid element value at %ld\n", i); + return -EINVAL; + } + accumulate_time(vcpu, &vcpu->arch.guest_exit); + + *tb = mftb(); + kvmppc_gsm_reset(io->vcpu_message); + kvmppc_gsm_reset(io->vcore_message); + kvmppc_gsbm_zero(&io->valids); + + rc = kvmhv_nestedv2_parse_output(vcpu); + if (rc < 0) + return -EINVAL; + + timer_rearm_host_dec(*tb); + + return trap; +} + /* call our hypervisor to load up HV regs and go */ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long lpcr, u64 *tb) { - struct kvmppc_vcore *vc = vcpu->arch.vcore; unsigned long host_psscr; unsigned long msr; struct hv_guest_state hvregs; @@ -4118,7 +4196,7 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns if (!(lpcr & LPCR_LD)) /* Sign extend if not using large decrementer */ dec = (s32) dec; *tb = mftb(); - vcpu->arch.dec_expires = dec + (*tb + vc->tb_offset); + vcpu->arch.dec_expires = dec + (*tb + kvmppc_get_tb_offset(vcpu)); timer_rearm_host_dec(*tb); @@ -4153,7 +4231,10 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, vcpu_vpa_increment_dispatch(vcpu); if (kvmhv_on_pseries()) { - trap = kvmhv_vcpu_entry_p9_nested(vcpu, time_limit, lpcr, tb); + if (kvmhv_is_nestedv1()) + trap = kvmhv_vcpu_entry_p9_nested(vcpu, time_limit, lpcr, tb); + else + trap = kvmhv_vcpu_entry_nestedv2(vcpu, time_limit, lpcr, tb); /* H_CEDE has to be handled now, not later */ if (trap == BOOK3S_INTERRUPT_SYSCALL && !nested && @@ -4176,7 +4257,7 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, __this_cpu_write(cpu_in_guest, NULL); if (trap == BOOK3S_INTERRUPT_SYSCALL && - !(vcpu->arch.shregs.msr & MSR_PR)) { + !(__kvmppc_get_msr_hv(vcpu) & MSR_PR)) { unsigned long req = kvmppc_get_gpr(vcpu, 3); /* @@ -4655,7 +4736,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, if (!nested) { kvmppc_core_prepare_to_enter(vcpu); - if (vcpu->arch.shregs.msr & MSR_EE) { + if (__kvmppc_get_msr_hv(vcpu) & MSR_EE) { if (xive_interrupt_pending(vcpu)) kvmppc_inject_interrupt_hv(vcpu, BOOK3S_INTERRUPT_EXTERNAL, 0); @@ -4677,7 +4758,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, tb = mftb(); - kvmppc_update_vpa_dispatch_p9(vcpu, vc, tb + vc->tb_offset); + kvmppc_update_vpa_dispatch_p9(vcpu, vc, tb + kvmppc_get_tb_offset(vcpu)); trace_kvm_guest_enter(vcpu); @@ -4844,7 +4925,7 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu) msr |= MSR_VSX; if ((cpu_has_feature(CPU_FTR_TM) || cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) && - (vcpu->arch.hfscr & HFSCR_TM)) + (kvmppc_get_hfscr_hv(vcpu) & HFSCR_TM)) msr |= MSR_TM; msr = msr_check_and_set(msr); @@ -4868,7 +4949,7 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu) if (run->exit_reason == KVM_EXIT_PAPR_HCALL) { accumulate_time(vcpu, &vcpu->arch.hcall); - if (WARN_ON_ONCE(vcpu->arch.shregs.msr & MSR_PR)) { + if (WARN_ON_ONCE(__kvmppc_get_msr_hv(vcpu) & MSR_PR)) { /* * These should have been caught reflected * into the guest by now. Final sanity check: @@ -5133,6 +5214,14 @@ void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask) if (++cores_done >= kvm->arch.online_vcores) break; } + + if (kvmhv_is_nestedv2()) { + struct kvm_vcpu *vcpu; + + kvm_for_each_vcpu(i, vcpu, kvm) { + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LPCR); + } + } } void kvmppc_setup_partition_table(struct kvm *kvm) @@ -5399,15 +5488,43 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) /* Allocate the guest's logical partition ID */ - lpid = kvmppc_alloc_lpid(); - if ((long)lpid < 0) - return -ENOMEM; - kvm->arch.lpid = lpid; + if (!kvmhv_is_nestedv2()) { + lpid = kvmppc_alloc_lpid(); + if ((long)lpid < 0) + return -ENOMEM; + kvm->arch.lpid = lpid; + } kvmppc_alloc_host_rm_ops(); kvmhv_vm_nested_init(kvm); + if (kvmhv_is_nestedv2()) { + long rc; + unsigned long guest_id; + + rc = plpar_guest_create(0, &guest_id); + + if (rc != H_SUCCESS) + pr_err("KVM: Create Guest hcall failed, rc=%ld\n", rc); + + switch (rc) { + case H_PARAMETER: + case H_FUNCTION: + case H_STATE: + return -EINVAL; + case H_NOT_ENOUGH_RESOURCES: + case H_ABORTED: + return -ENOMEM; + case H_AUTHORITY: + return -EPERM; + case H_NOT_AVAILABLE: + return -EBUSY; + } + kvm->arch.lpid = guest_id; + } + + /* * Since we don't flush the TLB when tearing down a VM, * and this lpid might have previously been used, @@ -5477,7 +5594,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) lpcr |= LPCR_HAIL; ret = kvmppc_init_vm_radix(kvm); if (ret) { - kvmppc_free_lpid(kvm->arch.lpid); + if (kvmhv_is_nestedv2()) + plpar_guest_delete(0, kvm->arch.lpid); + else + kvmppc_free_lpid(kvm->arch.lpid); return ret; } kvmppc_setup_partition_table(kvm); @@ -5567,10 +5687,14 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm) kvm->arch.process_table = 0; if (kvm->arch.secure_guest) uv_svm_terminate(kvm->arch.lpid); - kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0); + if (!kvmhv_is_nestedv2()) + kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0); } - kvmppc_free_lpid(kvm->arch.lpid); + if (kvmhv_is_nestedv2()) + plpar_guest_delete(0, kvm->arch.lpid); + else + kvmppc_free_lpid(kvm->arch.lpid); kvmppc_free_pimap(kvm); } @@ -5982,6 +6106,8 @@ static int kvmhv_enable_nested(struct kvm *kvm) return -ENODEV; if (!radix_enabled()) return -ENODEV; + if (kvmhv_is_nestedv2()) + return -ENODEV; /* kvm == NULL means the caller is testing if the capability exists */ if (kvm) diff --git a/arch/powerpc/kvm/book3s_hv.h b/arch/powerpc/kvm/book3s_hv.h index 2f2e59d7d433..47b2c815641e 100644 --- a/arch/powerpc/kvm/book3s_hv.h +++ b/arch/powerpc/kvm/book3s_hv.h @@ -3,6 +3,8 @@ /* * Privileged (non-hypervisor) host registers to save. */ +#include "asm/guest-state-buffer.h" + struct p9_host_os_sprs { unsigned long iamr; unsigned long amr; @@ -50,3 +52,77 @@ void accumulate_time(struct kvm_vcpu *vcpu, struct kvmhv_tb_accumulator *next); #define start_timing(vcpu, next) do {} while (0) #define end_timing(vcpu) do {} while (0) #endif + +static inline void __kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 val) +{ + vcpu->arch.shregs.msr = val; + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_MSR); +} + +static inline u64 __kvmppc_get_msr_hv(struct kvm_vcpu *vcpu) +{ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, KVMPPC_GSID_MSR) < 0); + return vcpu->arch.shregs.msr; +} + +#define KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_SET(reg, size, iden) \ +static inline void kvmppc_set_##reg ##_hv(struct kvm_vcpu *vcpu, u##size val) \ +{ \ + vcpu->arch.reg = val; \ + kvmhv_nestedv2_mark_dirty(vcpu, iden); \ +} + +#define KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_GET(reg, size, iden) \ +static inline u##size kvmppc_get_##reg ##_hv(struct kvm_vcpu *vcpu) \ +{ \ + kvmhv_nestedv2_cached_reload(vcpu, iden); \ + return vcpu->arch.reg; \ +} + +#define KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(reg, size, iden) \ + KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_SET(reg, size, iden) \ + KVMPPC_BOOK3S_HV_VCPU_ACCESSOR_GET(reg, size, iden) \ + +#define KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_SET(reg, size, iden) \ +static inline void kvmppc_set_##reg ##_hv(struct kvm_vcpu *vcpu, int i, u##size val) \ +{ \ + vcpu->arch.reg[i] = val; \ + kvmhv_nestedv2_mark_dirty(vcpu, iden(i)); \ +} + +#define KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_GET(reg, size, iden) \ +static inline u##size kvmppc_get_##reg ##_hv(struct kvm_vcpu *vcpu, int i) \ +{ \ + WARN_ON(kvmhv_nestedv2_cached_reload(vcpu, iden(i)) < 0); \ + return vcpu->arch.reg[i]; \ +} + +#define KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(reg, size, iden) \ + KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_SET(reg, size, iden) \ + KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR_GET(reg, size, iden) \ + +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(mmcra, 64, KVMPPC_GSID_MMCRA) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(hfscr, 64, KVMPPC_GSID_HFSCR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(fscr, 64, KVMPPC_GSID_FSCR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dscr, 64, KVMPPC_GSID_DSCR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(purr, 64, KVMPPC_GSID_PURR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(spurr, 64, KVMPPC_GSID_SPURR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(amr, 64, KVMPPC_GSID_AMR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(uamor, 64, KVMPPC_GSID_UAMOR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(siar, 64, KVMPPC_GSID_SIAR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(sdar, 64, KVMPPC_GSID_SDAR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(iamr, 64, KVMPPC_GSID_IAMR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawr0, 64, KVMPPC_GSID_DAWR0) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawr1, 64, KVMPPC_GSID_DAWR1) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawrx0, 64, KVMPPC_GSID_DAWRX0) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(dawrx1, 64, KVMPPC_GSID_DAWRX1) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ciabr, 64, KVMPPC_GSID_CIABR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(wort, 64, KVMPPC_GSID_WORT) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ppr, 64, KVMPPC_GSID_PPR) +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(ctrl, 64, KVMPPC_GSID_CTRL); + +KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(mmcr, 64, KVMPPC_GSID_MMCR) +KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(sier, 64, KVMPPC_GSID_SIER) +KVMPPC_BOOK3S_HV_VCPU_ARRAY_ACCESSOR(pmc, 32, KVMPPC_GSID_PMC) + +KVMPPC_BOOK3S_HV_VCPU_ACCESSOR(pspb, 32, KVMPPC_GSID_PSPB) diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 0f5b021fa559..fa0e3a22cac0 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -32,6 +32,7 @@ #include "book3s_xics.h" #include "book3s_xive.h" +#include "book3s_hv.h" /* * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206) @@ -182,9 +183,13 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present); long kvmppc_rm_h_random(struct kvm_vcpu *vcpu) { + unsigned long rand; + if (ppc_md.get_random_seed && - ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4])) + ppc_md.get_random_seed(&rand)) { + kvmppc_set_gpr(vcpu, 4, rand); return H_SUCCESS; + } return H_HARDWARE; } @@ -510,7 +515,7 @@ void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr) */ if ((msr & MSR_TS_MASK) == MSR_TS_MASK) msr &= ~MSR_TS_MASK; - vcpu->arch.shregs.msr = msr; + __kvmppc_set_msr_hv(vcpu, msr); kvmppc_end_cede(vcpu); } EXPORT_SYMBOL_GPL(kvmppc_set_msr_hv); @@ -548,7 +553,7 @@ static void inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags) kvmppc_set_srr0(vcpu, pc); kvmppc_set_srr1(vcpu, (msr & SRR1_MSR_BITS) | srr1_flags); kvmppc_set_pc(vcpu, new_pc); - vcpu->arch.shregs.msr = new_msr; + __kvmppc_set_msr_hv(vcpu, new_msr); } void kvmppc_inject_interrupt_hv(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags) diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c index 377d0b4a05ee..3b658b8696bc 100644 --- a/arch/powerpc/kvm/book3s_hv_nested.c +++ b/arch/powerpc/kvm/book3s_hv_nested.c @@ -428,10 +428,12 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu) return vcpu->arch.trap; } +unsigned long nested_capabilities; + long kvmhv_nested_init(void) { long int ptb_order; - unsigned long ptcr; + unsigned long ptcr, host_capabilities; long rc; if (!kvmhv_on_pseries()) @@ -439,6 +441,29 @@ long kvmhv_nested_init(void) if (!radix_enabled()) return -ENODEV; + rc = plpar_guest_get_capabilities(0, &host_capabilities); + if (rc == H_SUCCESS) { + unsigned long capabilities = 0; + + if (cpu_has_feature(CPU_FTR_ARCH_31)) + capabilities |= H_GUEST_CAP_POWER10; + if (cpu_has_feature(CPU_FTR_ARCH_300)) + capabilities |= H_GUEST_CAP_POWER9; + + nested_capabilities = capabilities & host_capabilities; + rc = plpar_guest_set_capabilities(0, nested_capabilities); + if (rc != H_SUCCESS) { + pr_err("kvm-hv: Could not configure parent hypervisor capabilities (rc=%ld)", + rc); + return -ENODEV; + } + + static_branch_enable(&__kvmhv_is_nestedv2); + return 0; + } + + pr_info("kvm-hv: nestedv2 get capabilities hcall failed, falling back to nestedv1 (rc=%ld)\n", + rc); /* Partition table entry is 1<<4 bytes in size, hence the 4. */ ptb_order = KVM_MAX_NESTED_GUESTS_SHIFT + 4; /* Minimum partition table size is 1<<12 bytes */ @@ -478,7 +503,7 @@ void kvmhv_nested_exit(void) } } -static void kvmhv_flush_lpid(unsigned int lpid) +static void kvmhv_flush_lpid(u64 lpid) { long rc; @@ -500,17 +525,22 @@ static void kvmhv_flush_lpid(unsigned int lpid) pr_err("KVM: TLB LPID invalidation hcall failed, rc=%ld\n", rc); } -void kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1) +void kvmhv_set_ptbl_entry(u64 lpid, u64 dw0, u64 dw1) { if (!kvmhv_on_pseries()) { mmu_partition_table_set_entry(lpid, dw0, dw1, true); return; } - pseries_partition_tb[lpid].patb0 = cpu_to_be64(dw0); - pseries_partition_tb[lpid].patb1 = cpu_to_be64(dw1); - /* L0 will do the necessary barriers */ - kvmhv_flush_lpid(lpid); + if (kvmhv_is_nestedv1()) { + pseries_partition_tb[lpid].patb0 = cpu_to_be64(dw0); + pseries_partition_tb[lpid].patb1 = cpu_to_be64(dw1); + /* L0 will do the necessary barriers */ + kvmhv_flush_lpid(lpid); + } + + if (kvmhv_is_nestedv2()) + kvmhv_nestedv2_set_ptbl_entry(lpid, dw0, dw1); } static void kvmhv_set_nested_ptbl(struct kvm_nested_guest *gp) diff --git a/arch/powerpc/kvm/book3s_hv_nestedv2.c b/arch/powerpc/kvm/book3s_hv_nestedv2.c new file mode 100644 index 000000000000..fd3c4f2d9480 --- /dev/null +++ b/arch/powerpc/kvm/book3s_hv_nestedv2.c @@ -0,0 +1,994 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2023 Jordan Niethe, IBM Corp. + * + * Authors: + * Jordan Niethe + * + * Description: KVM functions specific to running on Book 3S + * processors as a NESTEDv2 guest. + * + */ + +#include "linux/blk-mq.h" +#include "linux/console.h" +#include "linux/gfp_types.h" +#include "linux/signal.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "trace_hv.h" + +struct static_key_false __kvmhv_is_nestedv2 __read_mostly; +EXPORT_SYMBOL_GPL(__kvmhv_is_nestedv2); + + +static size_t +gs_msg_ops_kvmhv_nestedv2_config_get_size(struct kvmppc_gs_msg *gsm) +{ + u16 ids[] = { + KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE, + KVMPPC_GSID_RUN_INPUT, + KVMPPC_GSID_RUN_OUTPUT, + + }; + size_t size = 0; + + for (int i = 0; i < ARRAY_SIZE(ids); i++) + size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i])); + return size; +} + +static int +gs_msg_ops_kvmhv_nestedv2_config_fill_info(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm) +{ + struct kvmhv_nestedv2_config *cfg; + int rc; + + cfg = gsm->data; + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE)) { + rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE, + cfg->vcpu_run_output_size); + if (rc < 0) + return rc; + } + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT)) { + rc = kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT, + cfg->vcpu_run_input_cfg); + if (rc < 0) + return rc; + } + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_OUTPUT)) { + kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_OUTPUT, + cfg->vcpu_run_output_cfg); + if (rc < 0) + return rc; + } + + return 0; +} + +static int +gs_msg_ops_kvmhv_nestedv2_config_refresh_info(struct kvmppc_gs_msg *gsm, + struct kvmppc_gs_buff *gsb) +{ + struct kvmhv_nestedv2_config *cfg; + struct kvmppc_gs_parser gsp = { 0 }; + struct kvmppc_gs_elem *gse; + int rc; + + cfg = gsm->data; + + rc = kvmppc_gse_parse(&gsp, gsb); + if (rc < 0) + return rc; + + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE); + if (gse) + cfg->vcpu_run_output_size = kvmppc_gse_get_u64(gse); + return 0; +} + +static struct kvmppc_gs_msg_ops config_msg_ops = { + .get_size = gs_msg_ops_kvmhv_nestedv2_config_get_size, + .fill_info = gs_msg_ops_kvmhv_nestedv2_config_fill_info, + .refresh_info = gs_msg_ops_kvmhv_nestedv2_config_refresh_info, +}; + +static size_t gs_msg_ops_vcpu_get_size(struct kvmppc_gs_msg *gsm) +{ + struct kvmppc_gs_bitmap gsbm = { 0 }; + size_t size = 0; + u16 iden; + + kvmppc_gsbm_fill(&gsbm); + kvmppc_gsbm_for_each(&gsbm, iden) + { + switch (iden) { + case KVMPPC_GSID_HOST_STATE_SIZE: + case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE: + case KVMPPC_GSID_PARTITION_TABLE: + case KVMPPC_GSID_PROCESS_TABLE: + case KVMPPC_GSID_RUN_INPUT: + case KVMPPC_GSID_RUN_OUTPUT: + break; + default: + size += kvmppc_gse_total_size(kvmppc_gsid_size(iden)); + } + } + return size; +} + +static int gs_msg_ops_vcpu_fill_info(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm) +{ + struct kvm_vcpu *vcpu; + vector128 v; + int rc, i; + u16 iden; + + vcpu = gsm->data; + + kvmppc_gsm_for_each(gsm, iden) + { + rc = 0; + + if ((gsm->flags & KVMPPC_GS_FLAGS_WIDE) != + (kvmppc_gsid_flags(iden) & KVMPPC_GS_FLAGS_WIDE)) + continue; + + switch (iden) { + case KVMPPC_GSID_DSCR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dscr); + break; + case KVMPPC_GSID_MMCRA: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcra); + break; + case KVMPPC_GSID_HFSCR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.hfscr); + break; + case KVMPPC_GSID_PURR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.purr); + break; + case KVMPPC_GSID_SPURR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.spurr); + break; + case KVMPPC_GSID_AMR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.amr); + break; + case KVMPPC_GSID_UAMOR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.uamor); + break; + case KVMPPC_GSID_SIAR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.siar); + break; + case KVMPPC_GSID_SDAR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sdar); + break; + case KVMPPC_GSID_IAMR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.iamr); + break; + case KVMPPC_GSID_DAWR0: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr0); + break; + case KVMPPC_GSID_DAWR1: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.dawr1); + break; + case KVMPPC_GSID_DAWRX0: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx0); + break; + case KVMPPC_GSID_DAWRX1: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.dawrx1); + break; + case KVMPPC_GSID_CIABR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ciabr); + break; + case KVMPPC_GSID_WORT: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.wort); + break; + case KVMPPC_GSID_PPR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ppr); + break; + case KVMPPC_GSID_PSPB: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pspb); + break; + case KVMPPC_GSID_TAR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.tar); + break; + case KVMPPC_GSID_FSCR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fscr); + break; + case KVMPPC_GSID_EBBHR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbhr); + break; + case KVMPPC_GSID_EBBRR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ebbrr); + break; + case KVMPPC_GSID_BESCR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.bescr); + break; + case KVMPPC_GSID_IC: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ic); + break; + case KVMPPC_GSID_CTRL: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.ctrl); + break; + case KVMPPC_GSID_PIDR: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pid); + break; + case KVMPPC_GSID_AMOR: { + u64 amor = ~0; + + rc = kvmppc_gse_put_u64(gsb, iden, amor); + break; + } + case KVMPPC_GSID_VRSAVE: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.vrsave); + break; + case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3): + i = iden - KVMPPC_GSID_MMCR(0); + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.mmcr[i]); + break; + case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2): + i = iden - KVMPPC_GSID_SIER(0); + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.sier[i]); + break; + case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5): + i = iden - KVMPPC_GSID_PMC(0); + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.pmc[i]); + break; + case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31): + i = iden - KVMPPC_GSID_GPR(0); + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.regs.gpr[i]); + break; + case KVMPPC_GSID_CR: + rc = kvmppc_gse_put_u32(gsb, iden, vcpu->arch.regs.ccr); + break; + case KVMPPC_GSID_XER: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.xer); + break; + case KVMPPC_GSID_CTR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.ctr); + break; + case KVMPPC_GSID_LR: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.regs.link); + break; + case KVMPPC_GSID_NIA: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.regs.nip); + break; + case KVMPPC_GSID_SRR0: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.srr0); + break; + case KVMPPC_GSID_SRR1: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.srr1); + break; + case KVMPPC_GSID_SPRG0: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.sprg0); + break; + case KVMPPC_GSID_SPRG1: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.sprg1); + break; + case KVMPPC_GSID_SPRG2: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.sprg2); + break; + case KVMPPC_GSID_SPRG3: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.sprg3); + break; + case KVMPPC_GSID_DAR: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.dar); + break; + case KVMPPC_GSID_DSISR: + rc = kvmppc_gse_put_u32(gsb, iden, + vcpu->arch.shregs.dsisr); + break; + case KVMPPC_GSID_MSR: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.shregs.msr); + break; + case KVMPPC_GSID_VTB: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.vcore->vtb); + break; + case KVMPPC_GSID_LPCR: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.vcore->lpcr); + break; + case KVMPPC_GSID_TB_OFFSET: + rc = kvmppc_gse_put_u64(gsb, iden, + vcpu->arch.vcore->tb_offset); + break; + case KVMPPC_GSID_FPSCR: + rc = kvmppc_gse_put_u64(gsb, iden, vcpu->arch.fp.fpscr); + break; + case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31): + i = iden - KVMPPC_GSID_VSRS(0); + memcpy(&v, &vcpu->arch.fp.fpr[i], + sizeof(vcpu->arch.fp.fpr[i])); + rc = kvmppc_gse_put_vector128(gsb, iden, &v); + break; +#ifdef CONFIG_VSX + case KVMPPC_GSID_VSCR: + rc = kvmppc_gse_put_u32(gsb, iden, + vcpu->arch.vr.vscr.u[3]); + break; + case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63): + i = iden - KVMPPC_GSID_VSRS(32); + rc = kvmppc_gse_put_vector128(gsb, iden, + &vcpu->arch.vr.vr[i]); + break; +#endif + case KVMPPC_GSID_DEC_EXPIRY_TB: { + u64 dw; + + dw = vcpu->arch.dec_expires - + vcpu->arch.vcore->tb_offset; + rc = kvmppc_gse_put_u64(gsb, iden, dw); + break; + } + case KVMPPC_GSID_LOGICAL_PVR: + rc = kvmppc_gse_put_u32(gsb, iden, + vcpu->arch.vcore->arch_compat); + break; + } + + if (rc < 0) + return rc; + } + + return 0; +} + +static int gs_msg_ops_vcpu_refresh_info(struct kvmppc_gs_msg *gsm, + struct kvmppc_gs_buff *gsb) +{ + struct kvmppc_gs_parser gsp = { 0 }; + struct kvmhv_nestedv2_io *io; + struct kvmppc_gs_bitmap *valids; + struct kvm_vcpu *vcpu; + struct kvmppc_gs_elem *gse; + vector128 v; + int rc, i; + u16 iden; + + vcpu = gsm->data; + + rc = kvmppc_gse_parse(&gsp, gsb); + if (rc < 0) + return rc; + + io = &vcpu->arch.nestedv2_io; + valids = &io->valids; + + kvmppc_gsp_for_each(&gsp, iden, gse) + { + switch (iden) { + case KVMPPC_GSID_DSCR: + vcpu->arch.dscr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_MMCRA: + vcpu->arch.mmcra = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_HFSCR: + vcpu->arch.hfscr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_PURR: + vcpu->arch.purr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SPURR: + vcpu->arch.spurr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_AMR: + vcpu->arch.amr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_UAMOR: + vcpu->arch.uamor = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SIAR: + vcpu->arch.siar = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SDAR: + vcpu->arch.sdar = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_IAMR: + vcpu->arch.iamr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_DAWR0: + vcpu->arch.dawr0 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_DAWR1: + vcpu->arch.dawr1 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_DAWRX0: + vcpu->arch.dawrx0 = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_DAWRX1: + vcpu->arch.dawrx1 = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_CIABR: + vcpu->arch.ciabr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_WORT: + vcpu->arch.wort = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_PPR: + vcpu->arch.ppr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_PSPB: + vcpu->arch.pspb = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_TAR: + vcpu->arch.tar = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_FSCR: + vcpu->arch.fscr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_EBBHR: + vcpu->arch.ebbhr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_EBBRR: + vcpu->arch.ebbrr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_BESCR: + vcpu->arch.bescr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_IC: + vcpu->arch.ic = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_CTRL: + vcpu->arch.ctrl = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_PIDR: + vcpu->arch.pid = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_AMOR: + break; + case KVMPPC_GSID_VRSAVE: + vcpu->arch.vrsave = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_MMCR(0)... KVMPPC_GSID_MMCR(3): + i = iden - KVMPPC_GSID_MMCR(0); + vcpu->arch.mmcr[i] = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SIER(0)... KVMPPC_GSID_SIER(2): + i = iden - KVMPPC_GSID_SIER(0); + vcpu->arch.sier[i] = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_PMC(0)... KVMPPC_GSID_PMC(5): + i = iden - KVMPPC_GSID_PMC(0); + vcpu->arch.pmc[i] = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_GPR(0)... KVMPPC_GSID_GPR(31): + i = iden - KVMPPC_GSID_GPR(0); + vcpu->arch.regs.gpr[i] = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_CR: + vcpu->arch.regs.ccr = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_XER: + vcpu->arch.regs.xer = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_CTR: + vcpu->arch.regs.ctr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_LR: + vcpu->arch.regs.link = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_NIA: + vcpu->arch.regs.nip = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SRR0: + vcpu->arch.shregs.srr0 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SRR1: + vcpu->arch.shregs.srr1 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SPRG0: + vcpu->arch.shregs.sprg0 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SPRG1: + vcpu->arch.shregs.sprg1 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SPRG2: + vcpu->arch.shregs.sprg2 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_SPRG3: + vcpu->arch.shregs.sprg3 = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_DAR: + vcpu->arch.shregs.dar = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_DSISR: + vcpu->arch.shregs.dsisr = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_MSR: + vcpu->arch.shregs.msr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_VTB: + vcpu->arch.vcore->vtb = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_LPCR: + vcpu->arch.vcore->lpcr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_TB_OFFSET: + vcpu->arch.vcore->tb_offset = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_FPSCR: + vcpu->arch.fp.fpscr = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_VSRS(0)... KVMPPC_GSID_VSRS(31): + kvmppc_gse_get_vector128(gse, &v); + i = iden - KVMPPC_GSID_VSRS(0); + memcpy(&vcpu->arch.fp.fpr[i], &v, + sizeof(vcpu->arch.fp.fpr[i])); + break; +#ifdef CONFIG_VSX + case KVMPPC_GSID_VSCR: + vcpu->arch.vr.vscr.u[3] = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_VSRS(32)... KVMPPC_GSID_VSRS(63): + i = iden - KVMPPC_GSID_VSRS(32); + kvmppc_gse_get_vector128(gse, &vcpu->arch.vr.vr[i]); + break; +#endif + case KVMPPC_GSID_HDAR: + vcpu->arch.fault_dar = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_HDSISR: + vcpu->arch.fault_dsisr = kvmppc_gse_get_u32(gse); + break; + case KVMPPC_GSID_ASDR: + vcpu->arch.fault_gpa = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_HEIR: + vcpu->arch.emul_inst = kvmppc_gse_get_u64(gse); + break; + case KVMPPC_GSID_DEC_EXPIRY_TB: { + u64 dw; + + dw = kvmppc_gse_get_u64(gse); + vcpu->arch.dec_expires = + dw + vcpu->arch.vcore->tb_offset; + break; + } + case KVMPPC_GSID_LOGICAL_PVR: + vcpu->arch.vcore->arch_compat = kvmppc_gse_get_u32(gse); + break; + default: + continue; + } + kvmppc_gsbm_set(valids, iden); + } + + return 0; +} + +static struct kvmppc_gs_msg_ops vcpu_message_ops = { + .get_size = gs_msg_ops_vcpu_get_size, + .fill_info = gs_msg_ops_vcpu_fill_info, + .refresh_info = gs_msg_ops_vcpu_refresh_info, +}; + +static int kvmhv_nestedv2_host_create(struct kvm_vcpu *vcpu, + struct kvmhv_nestedv2_io *io) +{ + struct kvmhv_nestedv2_config *cfg; + struct kvmppc_gs_buff *gsb, *vcpu_run_output, *vcpu_run_input; + unsigned long guest_id, vcpu_id; + struct kvmppc_gs_msg *gsm, *vcpu_message, *vcore_message; + int rc; + + cfg = &io->cfg; + guest_id = vcpu->kvm->arch.lpid; + vcpu_id = vcpu->vcpu_id; + + gsm = kvmppc_gsm_new(&config_msg_ops, cfg, KVMPPC_GS_FLAGS_WIDE, + GFP_KERNEL); + if (!gsm) { + rc = -ENOMEM; + goto err; + } + + gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), guest_id, vcpu_id, + GFP_KERNEL); + if (!gsb) { + rc = -ENOMEM; + goto free_gsm; + } + + rc = kvmppc_gsb_receive_datum(gsb, gsm, + KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't get vcpu run output buffer minimum size\n"); + goto free_gsb; + } + + vcpu_run_output = kvmppc_gsb_new(cfg->vcpu_run_output_size, guest_id, + vcpu_id, GFP_KERNEL); + if (!vcpu_run_output) { + rc = -ENOMEM; + goto free_gsb; + } + + cfg->vcpu_run_output_cfg.address = kvmppc_gsb_paddress(vcpu_run_output); + cfg->vcpu_run_output_cfg.size = kvmppc_gsb_capacity(vcpu_run_output); + io->vcpu_run_output = vcpu_run_output; + + gsm->flags = 0; + rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_OUTPUT); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't set vcpu run output buffer\n"); + goto free_gs_out; + } + + vcpu_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu, 0, GFP_KERNEL); + if (!vcpu_message) { + rc = -ENOMEM; + goto free_gs_out; + } + kvmppc_gsm_include_all(vcpu_message); + + io->vcpu_message = vcpu_message; + + vcpu_run_input = kvmppc_gsb_new(kvmppc_gsm_size(vcpu_message), guest_id, + vcpu_id, GFP_KERNEL); + if (!vcpu_run_input) { + rc = -ENOMEM; + goto free_vcpu_message; + } + + io->vcpu_run_input = vcpu_run_input; + cfg->vcpu_run_input_cfg.address = kvmppc_gsb_paddress(vcpu_run_input); + cfg->vcpu_run_input_cfg.size = kvmppc_gsb_capacity(vcpu_run_input); + rc = kvmppc_gsb_send_datum(gsb, gsm, KVMPPC_GSID_RUN_INPUT); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't set vcpu run input buffer\n"); + goto free_vcpu_run_input; + } + + vcore_message = kvmppc_gsm_new(&vcpu_message_ops, vcpu, + KVMPPC_GS_FLAGS_WIDE, GFP_KERNEL); + if (!vcore_message) { + rc = -ENOMEM; + goto free_vcpu_run_input; + } + + kvmppc_gsm_include_all(vcore_message); + kvmppc_gsbm_clear(&vcore_message->bitmap, KVMPPC_GSID_LOGICAL_PVR); + io->vcore_message = vcore_message; + + kvmppc_gsbm_fill(&io->valids); + kvmppc_gsm_free(gsm); + kvmppc_gsb_free(gsb); + return 0; + +free_vcpu_run_input: + kvmppc_gsb_free(vcpu_run_input); +free_vcpu_message: + kvmppc_gsm_free(vcpu_message); +free_gs_out: + kvmppc_gsb_free(vcpu_run_output); +free_gsb: + kvmppc_gsb_free(gsb); +free_gsm: + kvmppc_gsm_free(gsm); +err: + return rc; +} + +/** + * __kvmhv_nestedv2_mark_dirty() - mark a Guest State ID to be sent to the host + * @vcpu: vcpu + * @iden: guest state ID + * + * Mark a guest state ID as having been changed by the L1 host and thus + * the new value must be sent to the L0 hypervisor. See kvmhv_nestedv2_flush_vcpu() + */ +int __kvmhv_nestedv2_mark_dirty(struct kvm_vcpu *vcpu, u16 iden) +{ + struct kvmhv_nestedv2_io *io; + struct kvmppc_gs_bitmap *valids; + struct kvmppc_gs_msg *gsm; + + if (!iden) + return 0; + + io = &vcpu->arch.nestedv2_io; + valids = &io->valids; + gsm = io->vcpu_message; + kvmppc_gsm_include(gsm, iden); + gsm = io->vcore_message; + kvmppc_gsm_include(gsm, iden); + kvmppc_gsbm_set(valids, iden); + return 0; +} +EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty); + +/** + * __kvmhv_nestedv2_cached_reload() - reload a Guest State ID from the host + * @vcpu: vcpu + * @iden: guest state ID + * + * Reload the value for the guest state ID from the L0 host into the L1 host. + * This is cached so that going out to the L0 host only happens if necessary. + */ +int __kvmhv_nestedv2_cached_reload(struct kvm_vcpu *vcpu, u16 iden) +{ + struct kvmhv_nestedv2_io *io; + struct kvmppc_gs_bitmap *valids; + struct kvmppc_gs_buff *gsb; + struct kvmppc_gs_msg gsm; + int rc; + + if (!iden) + return 0; + + io = &vcpu->arch.nestedv2_io; + valids = &io->valids; + if (kvmppc_gsbm_test(valids, iden)) + return 0; + + gsb = io->vcpu_run_input; + kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, kvmppc_gsid_flags(iden)); + rc = kvmppc_gsb_receive_datum(gsb, &gsm, iden); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't get GSID: 0x%x\n", iden); + return rc; + } + return 0; +} +EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_cached_reload); + +/** + * kvmhv_nestedv2_flush_vcpu() - send modified Guest State IDs to the host + * @vcpu: vcpu + * @time_limit: hdec expiry tb + * + * Send the values marked by __kvmhv_nestedv2_mark_dirty() to the L0 host. + * Thread wide values are copied to the H_GUEST_RUN_VCPU input buffer. Guest + * wide values need to be sent with H_GUEST_SET first. + * + * The hdec tb offset is always sent to L0 host. + */ +int kvmhv_nestedv2_flush_vcpu(struct kvm_vcpu *vcpu, u64 time_limit) +{ + struct kvmhv_nestedv2_io *io; + struct kvmppc_gs_buff *gsb; + struct kvmppc_gs_msg *gsm; + int rc; + + io = &vcpu->arch.nestedv2_io; + gsb = io->vcpu_run_input; + gsm = io->vcore_message; + rc = kvmppc_gsb_send_data(gsb, gsm); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't set guest wide elements\n"); + return rc; + } + + gsm = io->vcpu_message; + kvmppc_gsb_reset(gsb); + rc = kvmppc_gsm_fill_info(gsm, gsb); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't fill vcpu run input buffer\n"); + return rc; + } + + rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_HDEC_EXPIRY_TB, time_limit); + if (rc < 0) + return rc; + return 0; +} +EXPORT_SYMBOL_GPL(kvmhv_nestedv2_flush_vcpu); + +/** + * kvmhv_nestedv2_set_ptbl_entry() - send partition and process table state to + * L0 host + * @lpid: guest id + * @dw0: partition table double word + * @dw1: process table double word + */ +int kvmhv_nestedv2_set_ptbl_entry(unsigned long lpid, u64 dw0, u64 dw1) +{ + struct kvmppc_gs_part_table patbl; + struct kvmppc_gs_proc_table prtbl; + struct kvmppc_gs_buff *gsb; + size_t size; + int rc; + + size = kvmppc_gse_total_size( + kvmppc_gsid_size(KVMPPC_GSID_PARTITION_TABLE)) + + kvmppc_gse_total_size( + kvmppc_gsid_size(KVMPPC_GSID_PROCESS_TABLE)) + + sizeof(struct kvmppc_gs_header); + gsb = kvmppc_gsb_new(size, lpid, 0, GFP_KERNEL); + if (!gsb) + return -ENOMEM; + + patbl.address = dw0 & RPDB_MASK; + patbl.ea_bits = ((((dw0 & RTS1_MASK) >> (RTS1_SHIFT - 3)) | + ((dw0 & RTS2_MASK) >> RTS2_SHIFT)) + + 31); + patbl.gpd_size = 1ul << ((dw0 & RPDS_MASK) + 3); + rc = kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE, patbl); + if (rc < 0) + goto free_gsb; + + prtbl.address = dw1 & PRTB_MASK; + prtbl.gpd_size = 1ul << ((dw1 & PRTS_MASK) + 12); + rc = kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PROCESS_TABLE, prtbl); + if (rc < 0) + goto free_gsb; + + rc = kvmppc_gsb_send(gsb, KVMPPC_GS_FLAGS_WIDE); + if (rc < 0) { + pr_err("KVM-NESTEDv2: couldn't set the PATE\n"); + goto free_gsb; + } + + kvmppc_gsb_free(gsb); + return 0; + +free_gsb: + kvmppc_gsb_free(gsb); + return rc; +} +EXPORT_SYMBOL_GPL(kvmhv_nestedv2_set_ptbl_entry); + +/** + * kvmhv_nestedv2_parse_output() - receive values from H_GUEST_RUN_VCPU output + * @vcpu: vcpu + * + * Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu. + */ +int kvmhv_nestedv2_parse_output(struct kvm_vcpu *vcpu) +{ + struct kvmhv_nestedv2_io *io; + struct kvmppc_gs_buff *gsb; + struct kvmppc_gs_msg gsm; + + io = &vcpu->arch.nestedv2_io; + gsb = io->vcpu_run_output; + + vcpu->arch.fault_dar = 0; + vcpu->arch.fault_dsisr = 0; + vcpu->arch.fault_gpa = 0; + vcpu->arch.emul_inst = KVM_INST_FETCH_FAILED; + + kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0); + return kvmppc_gsm_refresh_info(&gsm, gsb); +} +EXPORT_SYMBOL_GPL(kvmhv_nestedv2_parse_output); + +static void kvmhv_nestedv2_host_free(struct kvm_vcpu *vcpu, + struct kvmhv_nestedv2_io *io) +{ + kvmppc_gsm_free(io->vcpu_message); + kvmppc_gsm_free(io->vcore_message); + kvmppc_gsb_free(io->vcpu_run_input); + kvmppc_gsb_free(io->vcpu_run_output); +} + +int __kvmhv_nestedv2_reload_ptregs(struct kvm_vcpu *vcpu, struct pt_regs *regs) +{ + struct kvmhv_nestedv2_io *io; + struct kvmppc_gs_bitmap *valids; + struct kvmppc_gs_buff *gsb; + struct kvmppc_gs_msg gsm; + int rc = 0; + + + io = &vcpu->arch.nestedv2_io; + valids = &io->valids; + + gsb = io->vcpu_run_input; + kvmppc_gsm_init(&gsm, &vcpu_message_ops, vcpu, 0); + + for (int i = 0; i < 32; i++) { + if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_GPR(i))) + kvmppc_gsm_include(&gsm, KVMPPC_GSID_GPR(i)); + } + + if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CR)) + kvmppc_gsm_include(&gsm, KVMPPC_GSID_CR); + + if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_XER)) + kvmppc_gsm_include(&gsm, KVMPPC_GSID_XER); + + if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_CTR)) + kvmppc_gsm_include(&gsm, KVMPPC_GSID_CTR); + + if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_LR)) + kvmppc_gsm_include(&gsm, KVMPPC_GSID_LR); + + if (!kvmppc_gsbm_test(valids, KVMPPC_GSID_NIA)) + kvmppc_gsm_include(&gsm, KVMPPC_GSID_NIA); + + rc = kvmppc_gsb_receive_data(gsb, &gsm); + if (rc < 0) + pr_err("KVM-NESTEDv2: couldn't reload ptregs\n"); + + return rc; +} +EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_reload_ptregs); + +int __kvmhv_nestedv2_mark_dirty_ptregs(struct kvm_vcpu *vcpu, + struct pt_regs *regs) +{ + for (int i = 0; i < 32; i++) + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_GPR(i)); + + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CR); + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_XER); + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_CTR); + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LR); + kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_NIA); + + return 0; +} +EXPORT_SYMBOL_GPL(__kvmhv_nestedv2_mark_dirty_ptregs); + +/** + * kvmhv_nestedv2_vcpu_create() - create nested vcpu for the NESTEDv2 API + * @vcpu: vcpu + * @io: NESTEDv2 nested io state + * + * Parse the output buffer from H_GUEST_RUN_VCPU to update vcpu. + */ +int kvmhv_nestedv2_vcpu_create(struct kvm_vcpu *vcpu, + struct kvmhv_nestedv2_io *io) +{ + long rc; + + rc = plpar_guest_create_vcpu(0, vcpu->kvm->arch.lpid, vcpu->vcpu_id); + + if (rc != H_SUCCESS) { + pr_err("KVM: Create Guest vcpu hcall failed, rc=%ld\n", rc); + switch (rc) { + case H_NOT_ENOUGH_RESOURCES: + case H_ABORTED: + return -ENOMEM; + case H_AUTHORITY: + return -EPERM; + default: + return -EINVAL; + } + } + + rc = kvmhv_nestedv2_host_create(vcpu, io); + + return rc; +} +EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_create); + +/** + * kvmhv_nestedv2_vcpu_free() - free the NESTEDv2 state + * @vcpu: vcpu + * @io: NESTEDv2 nested io state + */ +void kvmhv_nestedv2_vcpu_free(struct kvm_vcpu *vcpu, + struct kvmhv_nestedv2_io *io) +{ + kvmhv_nestedv2_host_free(vcpu, io); +} +EXPORT_SYMBOL_GPL(kvmhv_nestedv2_vcpu_free); diff --git a/arch/powerpc/kvm/book3s_hv_p9_entry.c b/arch/powerpc/kvm/book3s_hv_p9_entry.c index 34f1db212824..34bc0a8a1288 100644 --- a/arch/powerpc/kvm/book3s_hv_p9_entry.c +++ b/arch/powerpc/kvm/book3s_hv_p9_entry.c @@ -305,7 +305,7 @@ static void switch_mmu_to_guest_radix(struct kvm *kvm, struct kvm_vcpu *vcpu, u6 u32 pid; lpid = nested ? nested->shadow_lpid : kvm->arch.lpid; - pid = vcpu->arch.pid; + pid = kvmppc_get_pid(vcpu); /* * Prior memory accesses to host PID Q3 must be completed before we @@ -330,7 +330,7 @@ static void switch_mmu_to_guest_hpt(struct kvm *kvm, struct kvm_vcpu *vcpu, u64 int i; lpid = kvm->arch.lpid; - pid = vcpu->arch.pid; + pid = kvmppc_get_pid(vcpu); /* * See switch_mmu_to_guest_radix. ptesync should not be required here diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c index 82be6d87514b..9012acadbca8 100644 --- a/arch/powerpc/kvm/book3s_hv_ras.c +++ b/arch/powerpc/kvm/book3s_hv_ras.c @@ -174,14 +174,14 @@ long kvmppc_p9_realmode_hmi_handler(struct kvm_vcpu *vcpu) ppc_md.hmi_exception_early(NULL); out: - if (vc->tb_offset) { + if (kvmppc_get_tb_offset(vcpu)) { u64 new_tb = mftb() + vc->tb_offset; mtspr(SPRN_TBU40, new_tb); if ((mftb() & 0xffffff) < (new_tb & 0xffffff)) { new_tb += 0x1000000; mtspr(SPRN_TBU40, new_tb); } - vc->tb_offset_applied = vc->tb_offset; + vc->tb_offset_applied = kvmppc_get_tb_offset(vcpu); } return ret; diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 9182324dbef9..17cb75a127b0 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -776,8 +776,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C)); r &= ~HPTE_GR_RESERVED; } - vcpu->arch.regs.gpr[4 + i * 2] = v; - vcpu->arch.regs.gpr[5 + i * 2] = r; + kvmppc_set_gpr(vcpu, 4 + i * 2, v); + kvmppc_set_gpr(vcpu, 5 + i * 2, r); } return H_SUCCESS; } @@ -824,7 +824,7 @@ long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags, } } } - vcpu->arch.regs.gpr[4] = gr; + kvmppc_set_gpr(vcpu, 4, gr); ret = H_SUCCESS; out: unlock_hpte(hpte, v & ~HPTE_V_HVLOCK); @@ -872,7 +872,7 @@ long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags, kvmppc_set_dirty_from_hpte(kvm, v, gr); } } - vcpu->arch.regs.gpr[4] = gr; + kvmppc_set_gpr(vcpu, 4, gr); ret = H_SUCCESS; out: unlock_hpte(hpte, v & ~HPTE_V_HVLOCK); diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index e165bfa842bf..e42984878503 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c @@ -481,7 +481,7 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp, unsigned long xics_rm_h_xirr_x(struct kvm_vcpu *vcpu) { - vcpu->arch.regs.gpr[5] = get_tb(); + kvmppc_set_gpr(vcpu, 5, get_tb()); return xics_rm_h_xirr(vcpu); } @@ -518,7 +518,7 @@ unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu) } while (!icp_rm_try_update(icp, old_state, new_state)); /* Return the result in GPR4 */ - vcpu->arch.regs.gpr[4] = xirr; + kvmppc_set_gpr(vcpu, 4, xirr); return check_too_hard(xics, icp); } diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c index e2d6f9327f77..92f33115144b 100644 --- a/arch/powerpc/kvm/book3s_hv_uvmem.c +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c @@ -858,7 +858,7 @@ unsigned long kvmppc_h_svm_init_done(struct kvm *kvm) } kvm->arch.secure_guest |= KVMPPC_SECURE_INIT_DONE; - pr_info("LPID %d went secure\n", kvm->arch.lpid); + pr_info("LPID %lld went secure\n", kvm->arch.lpid); out: srcu_read_unlock(&kvm->srcu, srcu_idx); diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c index f4115819e738..29a382249770 100644 --- a/arch/powerpc/kvm/book3s_xive.c +++ b/arch/powerpc/kvm/book3s_xive.c @@ -328,7 +328,7 @@ static unsigned long xive_vm_h_xirr(struct kvm_vcpu *vcpu) */ /* Return interrupt and old CPPR in GPR4 */ - vcpu->arch.regs.gpr[4] = hirq | (old_cppr << 24); + kvmppc_set_gpr(vcpu, 4, hirq | (old_cppr << 24)); return H_SUCCESS; } @@ -364,7 +364,7 @@ static unsigned long xive_vm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server hirq = xive_vm_scan_interrupts(xc, pending, scan_poll); /* Return interrupt and old CPPR in GPR4 */ - vcpu->arch.regs.gpr[4] = hirq | (xc->cppr << 24); + kvmppc_set_gpr(vcpu, 4, hirq | (xc->cppr << 24)); return H_SUCCESS; } @@ -884,10 +884,10 @@ int kvmppc_xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio, } if (single_escalation) - name = kasprintf(GFP_KERNEL, "kvm-%d-%d", + name = kasprintf(GFP_KERNEL, "kvm-%lld-%d", vcpu->kvm->arch.lpid, xc->server_num); else - name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d", + name = kasprintf(GFP_KERNEL, "kvm-%lld-%d-%d", vcpu->kvm->arch.lpid, xc->server_num, prio); if (!name) { pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n", @@ -2779,8 +2779,6 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type) int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req) { - struct kvmppc_vcore *vc = vcpu->arch.vcore; - /* The VM should have configured XICS mode before doing XICS hcalls. */ if (!kvmppc_xics_enabled(vcpu)) return H_TOO_HARD; @@ -2799,7 +2797,7 @@ int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req) return xive_vm_h_ipoll(vcpu, kvmppc_get_gpr(vcpu, 4)); case H_XIRR_X: xive_vm_h_xirr(vcpu); - kvmppc_set_gpr(vcpu, 5, get_tb() + vc->tb_offset); + kvmppc_set_gpr(vcpu, 5, get_tb() + kvmppc_get_tb_offset(vcpu)); return H_SUCCESS; } diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c index 712ab91ced39..6e2ebbd8aaac 100644 --- a/arch/powerpc/kvm/book3s_xive_native.c +++ b/arch/powerpc/kvm/book3s_xive_native.c @@ -567,7 +567,7 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive, u8 priority; struct kvm_ppc_xive_eq kvm_eq; int rc; - __be32 *qaddr = 0; + __be32 *qaddr = NULL; struct page *page; struct xive_q *q; gfn_t gfn; diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c index 059c08ae0340..077fd88a0b68 100644 --- a/arch/powerpc/kvm/emulate_loadstore.c +++ b/arch/powerpc/kvm/emulate_loadstore.c @@ -92,7 +92,8 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) vcpu->arch.mmio_host_swabbed = 0; emulated = EMULATE_FAIL; - vcpu->arch.regs.msr = vcpu->arch.shared->msr; + vcpu->arch.regs.msr = kvmppc_get_msr(vcpu); + kvmhv_nestedv2_reload_ptregs(vcpu, &vcpu->arch.regs); if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) { int type = op.type & INSTR_TYPE_MASK; int size = GETSIZE(op.type); @@ -250,7 +251,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) vcpu->arch.mmio_sp64_extend = 1; emulated = kvmppc_handle_store(vcpu, - VCPU_FPR(vcpu, op.reg), size, 1); + kvmppc_get_fpr(vcpu, op.reg), size, 1); if ((op.type & UPDATE) && (emulated != EMULATE_FAIL)) kvmppc_set_gpr(vcpu, op.update_reg, op.ea); @@ -357,6 +358,7 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) } trace_kvm_ppc_instr(ppc_inst_val(inst), kvmppc_get_pc(vcpu), emulated); + kvmhv_nestedv2_mark_dirty_ptregs(vcpu, &vcpu->arch.regs); /* Advance past emulated instruction. */ if (emulated != EMULATE_FAIL) diff --git a/arch/powerpc/kvm/guest-state-buffer.c b/arch/powerpc/kvm/guest-state-buffer.c new file mode 100644 index 000000000000..b80dbc58621f --- /dev/null +++ b/arch/powerpc/kvm/guest-state-buffer.c @@ -0,0 +1,621 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "asm/hvcall.h" +#include +#include +#include + +static const u16 kvmppc_gse_iden_len[__KVMPPC_GSE_TYPE_MAX] = { + [KVMPPC_GSE_BE32] = sizeof(__be32), + [KVMPPC_GSE_BE64] = sizeof(__be64), + [KVMPPC_GSE_VEC128] = sizeof(vector128), + [KVMPPC_GSE_PARTITION_TABLE] = sizeof(struct kvmppc_gs_part_table), + [KVMPPC_GSE_PROCESS_TABLE] = sizeof(struct kvmppc_gs_proc_table), + [KVMPPC_GSE_BUFFER] = sizeof(struct kvmppc_gs_buff_info), +}; + +/** + * kvmppc_gsb_new() - create a new guest state buffer + * @size: total size of the guest state buffer (includes header) + * @guest_id: guest_id + * @vcpu_id: vcpu_id + * @flags: GFP flags + * + * Returns a guest state buffer. + */ +struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id, + unsigned long vcpu_id, gfp_t flags) +{ + struct kvmppc_gs_buff *gsb; + + gsb = kzalloc(sizeof(*gsb), flags); + if (!gsb) + return NULL; + + size = roundup_pow_of_two(size); + gsb->hdr = kzalloc(size, GFP_KERNEL); + if (!gsb->hdr) + goto free; + + gsb->capacity = size; + gsb->len = sizeof(struct kvmppc_gs_header); + gsb->vcpu_id = vcpu_id; + gsb->guest_id = guest_id; + + gsb->hdr->nelems = cpu_to_be32(0); + + return gsb; + +free: + kfree(gsb); + return NULL; +} +EXPORT_SYMBOL_GPL(kvmppc_gsb_new); + +/** + * kvmppc_gsb_free() - free a guest state buffer + * @gsb: guest state buffer + */ +void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb) +{ + kfree(gsb->hdr); + kfree(gsb); +} +EXPORT_SYMBOL_GPL(kvmppc_gsb_free); + +/** + * kvmppc_gsb_put() - allocate space in a guest state buffer + * @gsb: buffer to allocate in + * @size: amount of space to allocate + * + * Returns a pointer to the amount of space requested within the buffer and + * increments the count of elements in the buffer. + * + * Does not check if there is enough space in the buffer. + */ +void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size) +{ + u32 nelems = kvmppc_gsb_nelems(gsb); + void *p; + + p = (void *)kvmppc_gsb_header(gsb) + kvmppc_gsb_len(gsb); + gsb->len += size; + + kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(nelems + 1); + return p; +} +EXPORT_SYMBOL_GPL(kvmppc_gsb_put); + +static int kvmppc_gsid_class(u16 iden) +{ + if ((iden >= KVMPPC_GSE_GUESTWIDE_START) && + (iden <= KVMPPC_GSE_GUESTWIDE_END)) + return KVMPPC_GS_CLASS_GUESTWIDE; + + if ((iden >= KVMPPC_GSE_META_START) && (iden <= KVMPPC_GSE_META_END)) + return KVMPPC_GS_CLASS_META; + + if ((iden >= KVMPPC_GSE_DW_REGS_START) && + (iden <= KVMPPC_GSE_DW_REGS_END)) + return KVMPPC_GS_CLASS_DWORD_REG; + + if ((iden >= KVMPPC_GSE_W_REGS_START) && + (iden <= KVMPPC_GSE_W_REGS_END)) + return KVMPPC_GS_CLASS_WORD_REG; + + if ((iden >= KVMPPC_GSE_VSRS_START) && (iden <= KVMPPC_GSE_VSRS_END)) + return KVMPPC_GS_CLASS_VECTOR; + + if ((iden >= KVMPPC_GSE_INTR_REGS_START) && + (iden <= KVMPPC_GSE_INTR_REGS_END)) + return KVMPPC_GS_CLASS_INTR; + + return -1; +} + +static int kvmppc_gsid_type(u16 iden) +{ + int type = -1; + + switch (kvmppc_gsid_class(iden)) { + case KVMPPC_GS_CLASS_GUESTWIDE: + switch (iden) { + case KVMPPC_GSID_HOST_STATE_SIZE: + case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE: + case KVMPPC_GSID_TB_OFFSET: + type = KVMPPC_GSE_BE64; + break; + case KVMPPC_GSID_PARTITION_TABLE: + type = KVMPPC_GSE_PARTITION_TABLE; + break; + case KVMPPC_GSID_PROCESS_TABLE: + type = KVMPPC_GSE_PROCESS_TABLE; + break; + case KVMPPC_GSID_LOGICAL_PVR: + type = KVMPPC_GSE_BE32; + break; + } + break; + case KVMPPC_GS_CLASS_META: + switch (iden) { + case KVMPPC_GSID_RUN_INPUT: + case KVMPPC_GSID_RUN_OUTPUT: + type = KVMPPC_GSE_BUFFER; + break; + case KVMPPC_GSID_VPA: + type = KVMPPC_GSE_BE64; + break; + } + break; + case KVMPPC_GS_CLASS_DWORD_REG: + type = KVMPPC_GSE_BE64; + break; + case KVMPPC_GS_CLASS_WORD_REG: + type = KVMPPC_GSE_BE32; + break; + case KVMPPC_GS_CLASS_VECTOR: + type = KVMPPC_GSE_VEC128; + break; + case KVMPPC_GS_CLASS_INTR: + switch (iden) { + case KVMPPC_GSID_HDAR: + case KVMPPC_GSID_ASDR: + case KVMPPC_GSID_HEIR: + type = KVMPPC_GSE_BE64; + break; + case KVMPPC_GSID_HDSISR: + type = KVMPPC_GSE_BE32; + break; + } + break; + } + + return type; +} + +/** + * kvmppc_gsid_flags() - the flags for a guest state ID + * @iden: guest state ID + * + * Returns any flags for the guest state ID. + */ +unsigned long kvmppc_gsid_flags(u16 iden) +{ + unsigned long flags = 0; + + switch (kvmppc_gsid_class(iden)) { + case KVMPPC_GS_CLASS_GUESTWIDE: + flags = KVMPPC_GS_FLAGS_WIDE; + break; + case KVMPPC_GS_CLASS_META: + case KVMPPC_GS_CLASS_DWORD_REG: + case KVMPPC_GS_CLASS_WORD_REG: + case KVMPPC_GS_CLASS_VECTOR: + case KVMPPC_GS_CLASS_INTR: + break; + } + + return flags; +} +EXPORT_SYMBOL_GPL(kvmppc_gsid_flags); + +/** + * kvmppc_gsid_size() - the size of a guest state ID + * @iden: guest state ID + * + * Returns the size of guest state ID. + */ +u16 kvmppc_gsid_size(u16 iden) +{ + int type; + + type = kvmppc_gsid_type(iden); + if (type == -1) + return 0; + + if (type >= __KVMPPC_GSE_TYPE_MAX) + return 0; + + return kvmppc_gse_iden_len[type]; +} +EXPORT_SYMBOL_GPL(kvmppc_gsid_size); + +/** + * kvmppc_gsid_mask() - the settable bits of a guest state ID + * @iden: guest state ID + * + * Returns a mask of settable bits for a guest state ID. + */ +u64 kvmppc_gsid_mask(u16 iden) +{ + u64 mask = ~0ull; + + switch (iden) { + case KVMPPC_GSID_LPCR: + mask = LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_MER | + LPCR_GTSE; + break; + case KVMPPC_GSID_MSR: + mask = ~(MSR_HV | MSR_S | MSR_ME); + break; + } + + return mask; +} +EXPORT_SYMBOL_GPL(kvmppc_gsid_mask); + +/** + * __kvmppc_gse_put() - add a guest state element to a buffer + * @gsb: buffer to the element to + * @iden: guest state ID + * @size: length of data + * @data: pointer to data + */ +int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, + const void *data) +{ + struct kvmppc_gs_elem *gse; + u16 total_size; + + total_size = sizeof(*gse) + size; + if (total_size + kvmppc_gsb_len(gsb) > kvmppc_gsb_capacity(gsb)) + return -ENOMEM; + + if (kvmppc_gsid_size(iden) != size) + return -EINVAL; + + gse = kvmppc_gsb_put(gsb, total_size); + gse->iden = cpu_to_be16(iden); + gse->len = cpu_to_be16(size); + memcpy(gse->data, data, size); + + return 0; +} +EXPORT_SYMBOL_GPL(__kvmppc_gse_put); + +/** + * kvmppc_gse_parse() - create a parse map from a guest state buffer + * @gsp: guest state parser + * @gsb: guest state buffer + */ +int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb) +{ + struct kvmppc_gs_elem *curr; + int rem, i; + + kvmppc_gsb_for_each_elem(i, curr, gsb, rem) { + if (kvmppc_gse_len(curr) != + kvmppc_gsid_size(kvmppc_gse_iden(curr))) + return -EINVAL; + kvmppc_gsp_insert(gsp, kvmppc_gse_iden(curr), curr); + } + + if (kvmppc_gsb_nelems(gsb) != i) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(kvmppc_gse_parse); + +static inline int kvmppc_gse_flatten_iden(u16 iden) +{ + int bit = 0; + int class; + + class = kvmppc_gsid_class(iden); + + if (class == KVMPPC_GS_CLASS_GUESTWIDE) { + bit += iden - KVMPPC_GSE_GUESTWIDE_START; + return bit; + } + + bit += KVMPPC_GSE_GUESTWIDE_COUNT; + + if (class == KVMPPC_GS_CLASS_META) { + bit += iden - KVMPPC_GSE_META_START; + return bit; + } + + bit += KVMPPC_GSE_META_COUNT; + + if (class == KVMPPC_GS_CLASS_DWORD_REG) { + bit += iden - KVMPPC_GSE_DW_REGS_START; + return bit; + } + + bit += KVMPPC_GSE_DW_REGS_COUNT; + + if (class == KVMPPC_GS_CLASS_WORD_REG) { + bit += iden - KVMPPC_GSE_W_REGS_START; + return bit; + } + + bit += KVMPPC_GSE_W_REGS_COUNT; + + if (class == KVMPPC_GS_CLASS_VECTOR) { + bit += iden - KVMPPC_GSE_VSRS_START; + return bit; + } + + bit += KVMPPC_GSE_VSRS_COUNT; + + if (class == KVMPPC_GS_CLASS_INTR) { + bit += iden - KVMPPC_GSE_INTR_REGS_START; + return bit; + } + + return 0; +} + +static inline u16 kvmppc_gse_unflatten_iden(int bit) +{ + u16 iden; + + if (bit < KVMPPC_GSE_GUESTWIDE_COUNT) { + iden = KVMPPC_GSE_GUESTWIDE_START + bit; + return iden; + } + bit -= KVMPPC_GSE_GUESTWIDE_COUNT; + + if (bit < KVMPPC_GSE_META_COUNT) { + iden = KVMPPC_GSE_META_START + bit; + return iden; + } + bit -= KVMPPC_GSE_META_COUNT; + + if (bit < KVMPPC_GSE_DW_REGS_COUNT) { + iden = KVMPPC_GSE_DW_REGS_START + bit; + return iden; + } + bit -= KVMPPC_GSE_DW_REGS_COUNT; + + if (bit < KVMPPC_GSE_W_REGS_COUNT) { + iden = KVMPPC_GSE_W_REGS_START + bit; + return iden; + } + bit -= KVMPPC_GSE_W_REGS_COUNT; + + if (bit < KVMPPC_GSE_VSRS_COUNT) { + iden = KVMPPC_GSE_VSRS_START + bit; + return iden; + } + bit -= KVMPPC_GSE_VSRS_COUNT; + + if (bit < KVMPPC_GSE_IDEN_COUNT) { + iden = KVMPPC_GSE_INTR_REGS_START + bit; + return iden; + } + + return 0; +} + +/** + * kvmppc_gsp_insert() - add a mapping from an guest state ID to an element + * @gsp: guest state parser + * @iden: guest state id (key) + * @gse: guest state element (value) + */ +void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden, + struct kvmppc_gs_elem *gse) +{ + int i; + + i = kvmppc_gse_flatten_iden(iden); + kvmppc_gsbm_set(&gsp->iterator, iden); + gsp->gses[i] = gse; +} +EXPORT_SYMBOL_GPL(kvmppc_gsp_insert); + +/** + * kvmppc_gsp_lookup() - lookup an element from a guest state ID + * @gsp: guest state parser + * @iden: guest state ID (key) + * + * Returns the guest state element if present. + */ +struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp, u16 iden) +{ + int i; + + i = kvmppc_gse_flatten_iden(iden); + return gsp->gses[i]; +} +EXPORT_SYMBOL_GPL(kvmppc_gsp_lookup); + +/** + * kvmppc_gsbm_set() - set the guest state ID + * @gsbm: guest state bitmap + * @iden: guest state ID + */ +void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden) +{ + set_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap); +} +EXPORT_SYMBOL_GPL(kvmppc_gsbm_set); + +/** + * kvmppc_gsbm_clear() - clear the guest state ID + * @gsbm: guest state bitmap + * @iden: guest state ID + */ +void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden) +{ + clear_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap); +} +EXPORT_SYMBOL_GPL(kvmppc_gsbm_clear); + +/** + * kvmppc_gsbm_test() - test the guest state ID + * @gsbm: guest state bitmap + * @iden: guest state ID + */ +bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden) +{ + return test_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap); +} +EXPORT_SYMBOL_GPL(kvmppc_gsbm_test); + +/** + * kvmppc_gsbm_next() - return the next set guest state ID + * @gsbm: guest state bitmap + * @prev: last guest state ID + */ +u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev) +{ + int bit, pbit; + + pbit = prev ? kvmppc_gse_flatten_iden(prev) + 1 : 0; + bit = find_next_bit(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT, pbit); + + if (bit < KVMPPC_GSE_IDEN_COUNT) + return kvmppc_gse_unflatten_iden(bit); + return 0; +} +EXPORT_SYMBOL_GPL(kvmppc_gsbm_next); + +/** + * kvmppc_gsm_init() - initialize a guest state message + * @gsm: guest state message + * @ops: callbacks + * @data: private data + * @flags: guest wide or thread wide + */ +int kvmppc_gsm_init(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_msg_ops *ops, + void *data, unsigned long flags) +{ + memset(gsm, 0, sizeof(*gsm)); + gsm->ops = ops; + gsm->data = data; + gsm->flags = flags; + + return 0; +} +EXPORT_SYMBOL_GPL(kvmppc_gsm_init); + +/** + * kvmppc_gsm_new() - creates a new guest state message + * @ops: callbacks + * @data: private data + * @flags: guest wide or thread wide + * @gfp_flags: GFP allocation flags + * + * Returns an initialized guest state message. + */ +struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data, + unsigned long flags, gfp_t gfp_flags) +{ + struct kvmppc_gs_msg *gsm; + + gsm = kzalloc(sizeof(*gsm), gfp_flags); + if (!gsm) + return NULL; + + kvmppc_gsm_init(gsm, ops, data, flags); + + return gsm; +} +EXPORT_SYMBOL_GPL(kvmppc_gsm_new); + +/** + * kvmppc_gsm_size() - creates a new guest state message + * @gsm: self + * + * Returns the size required for the message. + */ +size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm) +{ + if (gsm->ops->get_size) + return gsm->ops->get_size(gsm); + return 0; +} +EXPORT_SYMBOL_GPL(kvmppc_gsm_size); + +/** + * kvmppc_gsm_free() - free guest state message + * @gsm: guest state message + * + * Returns the size required for the message. + */ +void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm) +{ + kfree(gsm); +} +EXPORT_SYMBOL_GPL(kvmppc_gsm_free); + +/** + * kvmppc_gsm_fill_info() - serialises message to guest state buffer format + * @gsm: self + * @gsb: buffer to serialise into + */ +int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb) +{ + if (!gsm->ops->fill_info) + return -EINVAL; + + return gsm->ops->fill_info(gsb, gsm); +} +EXPORT_SYMBOL_GPL(kvmppc_gsm_fill_info); + +/** + * kvmppc_gsm_refresh_info() - deserialises from guest state buffer + * @gsm: self + * @gsb: buffer to serialise from + */ +int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm, + struct kvmppc_gs_buff *gsb) +{ + if (!gsm->ops->fill_info) + return -EINVAL; + + return gsm->ops->refresh_info(gsm, gsb); +} +EXPORT_SYMBOL_GPL(kvmppc_gsm_refresh_info); + +/** + * kvmppc_gsb_send - send all elements in the buffer to the hypervisor. + * @gsb: guest state buffer + * @flags: guest wide or thread wide + * + * Performs the H_GUEST_SET_STATE hcall for the guest state buffer. + */ +int kvmppc_gsb_send(struct kvmppc_gs_buff *gsb, unsigned long flags) +{ + unsigned long hflags = 0; + unsigned long i; + int rc; + + if (kvmppc_gsb_nelems(gsb) == 0) + return 0; + + if (flags & KVMPPC_GS_FLAGS_WIDE) + hflags |= H_GUEST_FLAGS_WIDE; + + rc = plpar_guest_set_state(hflags, gsb->guest_id, gsb->vcpu_id, + __pa(gsb->hdr), gsb->capacity, &i); + return rc; +} +EXPORT_SYMBOL_GPL(kvmppc_gsb_send); + +/** + * kvmppc_gsb_recv - request all elements in the buffer have their value + * updated. + * @gsb: guest state buffer + * @flags: guest wide or thread wide + * + * Performs the H_GUEST_GET_STATE hcall for the guest state buffer. + * After returning from the hcall the guest state elements that were + * present in the buffer will have updated values from the hypervisor. + */ +int kvmppc_gsb_recv(struct kvmppc_gs_buff *gsb, unsigned long flags) +{ + unsigned long hflags = 0; + unsigned long i; + int rc; + + if (flags & KVMPPC_GS_FLAGS_WIDE) + hflags |= H_GUEST_FLAGS_WIDE; + + rc = plpar_guest_get_state(hflags, gsb->guest_id, gsb->vcpu_id, + __pa(gsb->hdr), gsb->capacity, &i); + return rc; +} +EXPORT_SYMBOL_GPL(kvmppc_gsb_recv); diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 7197c8256668..f6af752698d0 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -934,11 +934,11 @@ static inline void kvmppc_set_vsr_dword(struct kvm_vcpu *vcpu, return; if (index >= 32) { - val.vval = VCPU_VSX_VR(vcpu, index - 32); + kvmppc_get_vsx_vr(vcpu, index - 32, &val.vval); val.vsxval[offset] = gpr; - VCPU_VSX_VR(vcpu, index - 32) = val.vval; + kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval); } else { - VCPU_VSX_FPR(vcpu, index, offset) = gpr; + kvmppc_set_vsx_fpr(vcpu, index, offset, gpr); } } @@ -949,13 +949,13 @@ static inline void kvmppc_set_vsr_dword_dump(struct kvm_vcpu *vcpu, int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK; if (index >= 32) { - val.vval = VCPU_VSX_VR(vcpu, index - 32); + kvmppc_get_vsx_vr(vcpu, index - 32, &val.vval); val.vsxval[0] = gpr; val.vsxval[1] = gpr; - VCPU_VSX_VR(vcpu, index - 32) = val.vval; + kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval); } else { - VCPU_VSX_FPR(vcpu, index, 0) = gpr; - VCPU_VSX_FPR(vcpu, index, 1) = gpr; + kvmppc_set_vsx_fpr(vcpu, index, 0, gpr); + kvmppc_set_vsx_fpr(vcpu, index, 1, gpr); } } @@ -970,12 +970,12 @@ static inline void kvmppc_set_vsr_word_dump(struct kvm_vcpu *vcpu, val.vsx32val[1] = gpr; val.vsx32val[2] = gpr; val.vsx32val[3] = gpr; - VCPU_VSX_VR(vcpu, index - 32) = val.vval; + kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval); } else { val.vsx32val[0] = gpr; val.vsx32val[1] = gpr; - VCPU_VSX_FPR(vcpu, index, 0) = val.vsxval[0]; - VCPU_VSX_FPR(vcpu, index, 1) = val.vsxval[0]; + kvmppc_set_vsx_fpr(vcpu, index, 0, val.vsxval[0]); + kvmppc_set_vsx_fpr(vcpu, index, 1, val.vsxval[0]); } } @@ -991,15 +991,15 @@ static inline void kvmppc_set_vsr_word(struct kvm_vcpu *vcpu, return; if (index >= 32) { - val.vval = VCPU_VSX_VR(vcpu, index - 32); + kvmppc_get_vsx_vr(vcpu, index - 32, &val.vval); val.vsx32val[offset] = gpr32; - VCPU_VSX_VR(vcpu, index - 32) = val.vval; + kvmppc_set_vsx_vr(vcpu, index - 32, &val.vval); } else { dword_offset = offset / 2; word_offset = offset % 2; - val.vsxval[0] = VCPU_VSX_FPR(vcpu, index, dword_offset); + val.vsxval[0] = kvmppc_get_vsx_fpr(vcpu, index, dword_offset); val.vsx32val[word_offset] = gpr32; - VCPU_VSX_FPR(vcpu, index, dword_offset) = val.vsxval[0]; + kvmppc_set_vsx_fpr(vcpu, index, dword_offset, val.vsxval[0]); } } #endif /* CONFIG_VSX */ @@ -1058,9 +1058,9 @@ static inline void kvmppc_set_vmx_dword(struct kvm_vcpu *vcpu, if (offset == -1) return; - val.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, &val.vval); val.vsxval[offset] = gpr; - VCPU_VSX_VR(vcpu, index) = val.vval; + kvmppc_set_vsx_vr(vcpu, index, &val.vval); } static inline void kvmppc_set_vmx_word(struct kvm_vcpu *vcpu, @@ -1074,9 +1074,9 @@ static inline void kvmppc_set_vmx_word(struct kvm_vcpu *vcpu, if (offset == -1) return; - val.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, &val.vval); val.vsx32val[offset] = gpr32; - VCPU_VSX_VR(vcpu, index) = val.vval; + kvmppc_set_vsx_vr(vcpu, index, &val.vval); } static inline void kvmppc_set_vmx_hword(struct kvm_vcpu *vcpu, @@ -1090,9 +1090,9 @@ static inline void kvmppc_set_vmx_hword(struct kvm_vcpu *vcpu, if (offset == -1) return; - val.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, &val.vval); val.vsx16val[offset] = gpr16; - VCPU_VSX_VR(vcpu, index) = val.vval; + kvmppc_set_vsx_vr(vcpu, index, &val.vval); } static inline void kvmppc_set_vmx_byte(struct kvm_vcpu *vcpu, @@ -1106,9 +1106,9 @@ static inline void kvmppc_set_vmx_byte(struct kvm_vcpu *vcpu, if (offset == -1) return; - val.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, &val.vval); val.vsx8val[offset] = gpr8; - VCPU_VSX_VR(vcpu, index) = val.vval; + kvmppc_set_vsx_vr(vcpu, index, &val.vval); } #endif /* CONFIG_ALTIVEC */ @@ -1194,14 +1194,14 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu) if (vcpu->kvm->arch.kvm_ops->giveup_ext) vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu, MSR_FP); - VCPU_FPR(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK) = gpr; + kvmppc_set_fpr(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK, gpr); break; #ifdef CONFIG_PPC_BOOK3S case KVM_MMIO_REG_QPR: vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr; break; case KVM_MMIO_REG_FQPR: - VCPU_FPR(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK) = gpr; + kvmppc_set_fpr(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK, gpr); vcpu->arch.qpr[vcpu->arch.io_gpr & KVM_MMIO_REG_MASK] = gpr; break; #endif @@ -1419,9 +1419,9 @@ static inline int kvmppc_get_vsr_data(struct kvm_vcpu *vcpu, int rs, u64 *val) } if (rs < 32) { - *val = VCPU_VSX_FPR(vcpu, rs, vsx_offset); + *val = kvmppc_get_vsx_fpr(vcpu, rs, vsx_offset); } else { - reg.vval = VCPU_VSX_VR(vcpu, rs - 32); + kvmppc_get_vsx_vr(vcpu, rs - 32, ®.vval); *val = reg.vsxval[vsx_offset]; } break; @@ -1438,10 +1438,10 @@ static inline int kvmppc_get_vsr_data(struct kvm_vcpu *vcpu, int rs, u64 *val) if (rs < 32) { dword_offset = vsx_offset / 2; word_offset = vsx_offset % 2; - reg.vsxval[0] = VCPU_VSX_FPR(vcpu, rs, dword_offset); + reg.vsxval[0] = kvmppc_get_vsx_fpr(vcpu, rs, dword_offset); *val = reg.vsx32val[word_offset]; } else { - reg.vval = VCPU_VSX_VR(vcpu, rs - 32); + kvmppc_get_vsx_vr(vcpu, rs - 32, ®.vval); *val = reg.vsx32val[vsx_offset]; } break; @@ -1556,7 +1556,7 @@ static int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) if (vmx_offset == -1) return -1; - reg.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, ®.vval); *val = reg.vsxval[vmx_offset]; return result; @@ -1574,7 +1574,7 @@ static int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) if (vmx_offset == -1) return -1; - reg.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, ®.vval); *val = reg.vsx32val[vmx_offset]; return result; @@ -1592,7 +1592,7 @@ static int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) if (vmx_offset == -1) return -1; - reg.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, ®.vval); *val = reg.vsx16val[vmx_offset]; return result; @@ -1610,7 +1610,7 @@ static int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val) if (vmx_offset == -1) return -1; - reg.vval = VCPU_VSX_VR(vcpu, index); + kvmppc_get_vsx_vr(vcpu, index, ®.vval); *val = reg.vsx8val[vmx_offset]; return result; @@ -1719,17 +1719,17 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) r = -ENXIO; break; } - val.vval = vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0]; + kvmppc_get_vsx_vr(vcpu, reg->id - KVM_REG_PPC_VR0, &val.vval); break; case KVM_REG_PPC_VSCR: if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { r = -ENXIO; break; } - val = get_reg_val(reg->id, vcpu->arch.vr.vscr.u[3]); + val = get_reg_val(reg->id, kvmppc_get_vscr(vcpu)); break; case KVM_REG_PPC_VRSAVE: - val = get_reg_val(reg->id, vcpu->arch.vrsave); + val = get_reg_val(reg->id, kvmppc_get_vrsave(vcpu)); break; #endif /* CONFIG_ALTIVEC */ default: @@ -1770,21 +1770,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) r = -ENXIO; break; } - vcpu->arch.vr.vr[reg->id - KVM_REG_PPC_VR0] = val.vval; + kvmppc_set_vsx_vr(vcpu, reg->id - KVM_REG_PPC_VR0, &val.vval); break; case KVM_REG_PPC_VSCR: if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { r = -ENXIO; break; } - vcpu->arch.vr.vscr.u[3] = set_reg_val(reg->id, val); + kvmppc_set_vscr(vcpu, set_reg_val(reg->id, val)); break; case KVM_REG_PPC_VRSAVE: if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { r = -ENXIO; break; } - vcpu->arch.vrsave = set_reg_val(reg->id, val); + kvmppc_set_vrsave(vcpu, set_reg_val(reg->id, val)); break; #endif /* CONFIG_ALTIVEC */ default: diff --git a/arch/powerpc/kvm/test-guest-state-buffer.c b/arch/powerpc/kvm/test-guest-state-buffer.c new file mode 100644 index 000000000000..4720b8dc8837 --- /dev/null +++ b/arch/powerpc/kvm/test-guest-state-buffer.c @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include + +#include + +static void test_creating_buffer(struct kunit *test) +{ + struct kvmppc_gs_buff *gsb; + size_t size = 0x100; + + gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb->hdr); + + KUNIT_EXPECT_EQ(test, gsb->capacity, roundup_pow_of_two(size)); + KUNIT_EXPECT_EQ(test, gsb->len, sizeof(__be32)); + + kvmppc_gsb_free(gsb); +} + +static void test_adding_element(struct kunit *test) +{ + const struct kvmppc_gs_elem *head, *curr; + union { + __vector128 v; + u64 dw[2]; + } u; + int rem; + struct kvmppc_gs_buff *gsb; + size_t size = 0x1000; + int i, rc; + u64 data; + + gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); + + /* Single elements, direct use of __kvmppc_gse_put() */ + data = 0xdeadbeef; + rc = __kvmppc_gse_put(gsb, KVMPPC_GSID_GPR(0), 8, &data); + KUNIT_EXPECT_GE(test, rc, 0); + + head = kvmppc_gsb_data(gsb); + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(head), KVMPPC_GSID_GPR(0)); + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(head), 8); + data = 0; + memcpy(&data, kvmppc_gse_data(head), 8); + KUNIT_EXPECT_EQ(test, data, 0xdeadbeef); + + /* Multiple elements, simple wrapper */ + rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(1), 0xcafef00d); + KUNIT_EXPECT_GE(test, rc, 0); + + u.dw[0] = 0x1; + u.dw[1] = 0x2; + rc = kvmppc_gse_put_vector128(gsb, KVMPPC_GSID_VSRS(0), &u.v); + KUNIT_EXPECT_GE(test, rc, 0); + u.dw[0] = 0x0; + u.dw[1] = 0x0; + + kvmppc_gsb_for_each_elem(i, curr, gsb, rem) { + switch (i) { + case 0: + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr), + KVMPPC_GSID_GPR(0)); + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8); + KUNIT_EXPECT_EQ(test, kvmppc_gse_get_be64(curr), + 0xdeadbeef); + break; + case 1: + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr), + KVMPPC_GSID_GPR(1)); + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8); + KUNIT_EXPECT_EQ(test, kvmppc_gse_get_u64(curr), + 0xcafef00d); + break; + case 2: + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr), + KVMPPC_GSID_VSRS(0)); + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 16); + kvmppc_gse_get_vector128(curr, &u.v); + KUNIT_EXPECT_EQ(test, u.dw[0], 0x1); + KUNIT_EXPECT_EQ(test, u.dw[1], 0x2); + break; + } + } + KUNIT_EXPECT_EQ(test, i, 3); + + kvmppc_gsb_reset(gsb); + KUNIT_EXPECT_EQ(test, kvmppc_gsb_nelems(gsb), 0); + KUNIT_EXPECT_EQ(test, kvmppc_gsb_len(gsb), + sizeof(struct kvmppc_gs_header)); + + kvmppc_gsb_free(gsb); +} + +static void test_gs_parsing(struct kunit *test) +{ + struct kvmppc_gs_elem *gse; + struct kvmppc_gs_parser gsp = { 0 }; + struct kvmppc_gs_buff *gsb; + size_t size = 0x1000; + u64 tmp1, tmp2; + + gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); + + tmp1 = 0xdeadbeefull; + kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), tmp1); + + KUNIT_EXPECT_GE(test, kvmppc_gse_parse(&gsp, gsb), 0); + + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0)); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gse); + + tmp2 = kvmppc_gse_get_u64(gse); + KUNIT_EXPECT_EQ(test, tmp2, 0xdeadbeefull); + + kvmppc_gsb_free(gsb); +} + +static void test_gs_bitmap(struct kunit *test) +{ + struct kvmppc_gs_bitmap gsbm = { 0 }; + struct kvmppc_gs_bitmap gsbm1 = { 0 }; + struct kvmppc_gs_bitmap gsbm2 = { 0 }; + u16 iden; + int i, j; + + i = 0; + for (u16 iden = KVMPPC_GSID_HOST_STATE_SIZE; + iden <= KVMPPC_GSID_PROCESS_TABLE; iden++) { + kvmppc_gsbm_set(&gsbm, iden); + kvmppc_gsbm_set(&gsbm1, iden); + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); + kvmppc_gsbm_clear(&gsbm, iden); + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); + i++; + } + + for (u16 iden = KVMPPC_GSID_RUN_INPUT; iden <= KVMPPC_GSID_VPA; + iden++) { + kvmppc_gsbm_set(&gsbm, iden); + kvmppc_gsbm_set(&gsbm1, iden); + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); + kvmppc_gsbm_clear(&gsbm, iden); + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); + i++; + } + + for (u16 iden = KVMPPC_GSID_GPR(0); iden <= KVMPPC_GSID_CTRL; iden++) { + kvmppc_gsbm_set(&gsbm, iden); + kvmppc_gsbm_set(&gsbm1, iden); + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); + kvmppc_gsbm_clear(&gsbm, iden); + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); + i++; + } + + for (u16 iden = KVMPPC_GSID_CR; iden <= KVMPPC_GSID_PSPB; iden++) { + kvmppc_gsbm_set(&gsbm, iden); + kvmppc_gsbm_set(&gsbm1, iden); + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); + kvmppc_gsbm_clear(&gsbm, iden); + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); + i++; + } + + for (u16 iden = KVMPPC_GSID_VSRS(0); iden <= KVMPPC_GSID_VSRS(63); + iden++) { + kvmppc_gsbm_set(&gsbm, iden); + kvmppc_gsbm_set(&gsbm1, iden); + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); + kvmppc_gsbm_clear(&gsbm, iden); + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); + i++; + } + + for (u16 iden = KVMPPC_GSID_HDAR; iden <= KVMPPC_GSID_ASDR; iden++) { + kvmppc_gsbm_set(&gsbm, iden); + kvmppc_gsbm_set(&gsbm1, iden); + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); + kvmppc_gsbm_clear(&gsbm, iden); + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); + i++; + } + + j = 0; + kvmppc_gsbm_for_each(&gsbm1, iden) + { + kvmppc_gsbm_set(&gsbm2, iden); + j++; + } + KUNIT_EXPECT_EQ(test, i, j); + KUNIT_EXPECT_MEMEQ(test, &gsbm1, &gsbm2, sizeof(gsbm1)); +} + +struct kvmppc_gs_msg_test1_data { + u64 a; + u32 b; + struct kvmppc_gs_part_table c; + struct kvmppc_gs_proc_table d; + struct kvmppc_gs_buff_info e; +}; + +static size_t test1_get_size(struct kvmppc_gs_msg *gsm) +{ + size_t size = 0; + u16 ids[] = { + KVMPPC_GSID_PARTITION_TABLE, + KVMPPC_GSID_PROCESS_TABLE, + KVMPPC_GSID_RUN_INPUT, + KVMPPC_GSID_GPR(0), + KVMPPC_GSID_CR, + }; + + for (int i = 0; i < ARRAY_SIZE(ids); i++) + size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i])); + return size; +} + +static int test1_fill_info(struct kvmppc_gs_buff *gsb, + struct kvmppc_gs_msg *gsm) +{ + struct kvmppc_gs_msg_test1_data *data = gsm->data; + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_GPR(0))) + kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), data->a); + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_CR)) + kvmppc_gse_put_u32(gsb, KVMPPC_GSID_CR, data->b); + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PARTITION_TABLE)) + kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE, + data->c); + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PROCESS_TABLE)) + kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PARTITION_TABLE, + data->d); + + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT)) + kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT, data->e); + + return 0; +} + +static int test1_refresh_info(struct kvmppc_gs_msg *gsm, + struct kvmppc_gs_buff *gsb) +{ + struct kvmppc_gs_parser gsp = { 0 }; + struct kvmppc_gs_msg_test1_data *data = gsm->data; + struct kvmppc_gs_elem *gse; + int rc; + + rc = kvmppc_gse_parse(&gsp, gsb); + if (rc < 0) + return rc; + + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0)); + if (gse) + data->a = kvmppc_gse_get_u64(gse); + + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_CR); + if (gse) + data->b = kvmppc_gse_get_u32(gse); + + return 0; +} + +static struct kvmppc_gs_msg_ops gs_msg_test1_ops = { + .get_size = test1_get_size, + .fill_info = test1_fill_info, + .refresh_info = test1_refresh_info, +}; + +static void test_gs_msg(struct kunit *test) +{ + struct kvmppc_gs_msg_test1_data test1_data = { + .a = 0xdeadbeef, + .b = 0x1, + }; + struct kvmppc_gs_msg *gsm; + struct kvmppc_gs_buff *gsb; + + gsm = kvmppc_gsm_new(&gs_msg_test1_ops, &test1_data, GSM_SEND, + GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsm); + + gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), 0, 0, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); + + kvmppc_gsm_include(gsm, KVMPPC_GSID_PARTITION_TABLE); + kvmppc_gsm_include(gsm, KVMPPC_GSID_PROCESS_TABLE); + kvmppc_gsm_include(gsm, KVMPPC_GSID_RUN_INPUT); + kvmppc_gsm_include(gsm, KVMPPC_GSID_GPR(0)); + kvmppc_gsm_include(gsm, KVMPPC_GSID_CR); + + kvmppc_gsm_fill_info(gsm, gsb); + + memset(&test1_data, 0, sizeof(test1_data)); + + kvmppc_gsm_refresh_info(gsm, gsb); + KUNIT_EXPECT_EQ(test, test1_data.a, 0xdeadbeef); + KUNIT_EXPECT_EQ(test, test1_data.b, 0x1); + + kvmppc_gsm_free(gsm); +} + +static struct kunit_case guest_state_buffer_testcases[] = { + KUNIT_CASE(test_creating_buffer), + KUNIT_CASE(test_adding_element), + KUNIT_CASE(test_gs_bitmap), + KUNIT_CASE(test_gs_parsing), + KUNIT_CASE(test_gs_msg), + {} +}; + +static struct kunit_suite guest_state_buffer_test_suite = { + .name = "guest_state_buffer_test", + .test_cases = guest_state_buffer_testcases, +}; + +kunit_test_suites(&guest_state_buffer_test_suite); + +MODULE_LICENSE("GPL"); diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index b00112d7ad46..c6ab46156cda 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -38,6 +38,7 @@ static int __patch_instruction(u32 *exec_addr, ppc_inst_t instr, u32 *patch_addr return 0; failed: + mb(); /* sync */ return -EPERM; } @@ -204,9 +205,6 @@ void __init poking_init(void) { int ret; - if (!IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) - return; - if (mm_patch_enabled()) ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/text_poke_mm:online", @@ -309,10 +307,6 @@ static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) err = __patch_instruction(addr, instr, patch_addr); - /* hwsync performed by __patch_instruction (sync) if successful */ - if (err) - mb(); /* sync */ - /* context synchronisation performed by __patch_instruction (isync or exception) */ stop_using_temp_mm(patching_mm, orig_mm); @@ -378,6 +372,144 @@ int patch_instruction(u32 *addr, ppc_inst_t instr) } NOKPROBE_SYMBOL(patch_instruction); +static int __patch_instructions(u32 *patch_addr, u32 *code, size_t len, bool repeat_instr) +{ + unsigned long start = (unsigned long)patch_addr; + + /* Repeat instruction */ + if (repeat_instr) { + ppc_inst_t instr = ppc_inst_read(code); + + if (ppc_inst_prefixed(instr)) { + u64 val = ppc_inst_as_ulong(instr); + + memset64((u64 *)patch_addr, val, len / 8); + } else { + u32 val = ppc_inst_val(instr); + + memset32(patch_addr, val, len / 4); + } + } else { + memcpy(patch_addr, code, len); + } + + smp_wmb(); /* smp write barrier */ + flush_icache_range(start, start + len); + return 0; +} + +/* + * A page is mapped and instructions that fit the page are patched. + * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below. + */ +static int __do_patch_instructions_mm(u32 *addr, u32 *code, size_t len, bool repeat_instr) +{ + struct mm_struct *patching_mm, *orig_mm; + unsigned long pfn = get_patch_pfn(addr); + unsigned long text_poke_addr; + spinlock_t *ptl; + u32 *patch_addr; + pte_t *pte; + int err; + + patching_mm = __this_cpu_read(cpu_patching_context.mm); + text_poke_addr = __this_cpu_read(cpu_patching_context.addr); + patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr)); + + pte = get_locked_pte(patching_mm, text_poke_addr, &ptl); + if (!pte) + return -ENOMEM; + + __set_pte_at(patching_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0); + + /* order PTE update before use, also serves as the hwsync */ + asm volatile("ptesync" ::: "memory"); + + /* order context switch after arbitrary prior code */ + isync(); + + orig_mm = start_using_temp_mm(patching_mm); + + err = __patch_instructions(patch_addr, code, len, repeat_instr); + + /* context synchronisation performed by __patch_instructions */ + stop_using_temp_mm(patching_mm, orig_mm); + + pte_clear(patching_mm, text_poke_addr, pte); + /* + * ptesync to order PTE update before TLB invalidation done + * by radix__local_flush_tlb_page_psize (in _tlbiel_va) + */ + local_flush_tlb_page_psize(patching_mm, text_poke_addr, mmu_virtual_psize); + + pte_unmap_unlock(pte, ptl); + + return err; +} + +/* + * A page is mapped and instructions that fit the page are patched. + * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below. + */ +static int __do_patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr) +{ + unsigned long pfn = get_patch_pfn(addr); + unsigned long text_poke_addr; + u32 *patch_addr; + pte_t *pte; + int err; + + text_poke_addr = (unsigned long)__this_cpu_read(cpu_patching_context.addr) & PAGE_MASK; + patch_addr = (u32 *)(text_poke_addr + offset_in_page(addr)); + + pte = __this_cpu_read(cpu_patching_context.pte); + __set_pte_at(&init_mm, text_poke_addr, pte, pfn_pte(pfn, PAGE_KERNEL), 0); + /* See ptesync comment in radix__set_pte_at() */ + if (radix_enabled()) + asm volatile("ptesync" ::: "memory"); + + err = __patch_instructions(patch_addr, code, len, repeat_instr); + + pte_clear(&init_mm, text_poke_addr, pte); + flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE); + + return err; +} + +/* + * Patch 'addr' with 'len' bytes of instructions from 'code'. + * + * If repeat_instr is true, the same instruction is filled for + * 'len' bytes. + */ +int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr) +{ + while (len > 0) { + unsigned long flags; + size_t plen; + int err; + + plen = min_t(size_t, PAGE_SIZE - offset_in_page(addr), len); + + local_irq_save(flags); + if (mm_patch_enabled()) + err = __do_patch_instructions_mm(addr, code, plen, repeat_instr); + else + err = __do_patch_instructions(addr, code, plen, repeat_instr); + local_irq_restore(flags); + if (err) + return err; + + len -= plen; + addr = (u32 *)((unsigned long)addr + plen); + if (!repeat_instr) + code = (u32 *)((unsigned long)code + plen); + } + + return 0; +} +NOKPROBE_SYMBOL(patch_instructions); + int patch_branch(u32 *addr, unsigned long target, int flags) { ppc_inst_t instr; diff --git a/arch/powerpc/lib/qspinlock.c b/arch/powerpc/lib/qspinlock.c index 6dd2f46bd3ef..5de4dd549f6e 100644 --- a/arch/powerpc/lib/qspinlock.c +++ b/arch/powerpc/lib/qspinlock.c @@ -16,7 +16,8 @@ struct qnode { struct qnode *next; struct qspinlock *lock; int cpu; - int yield_cpu; + u8 sleepy; /* 1 if the previous vCPU was preempted or + * if the previous node was sleepy */ u8 locked; /* 1 if lock acquired */ }; @@ -43,7 +44,7 @@ static bool pv_sleepy_lock_sticky __read_mostly = false; static u64 pv_sleepy_lock_interval_ns __read_mostly = 0; static int pv_sleepy_lock_factor __read_mostly = 256; static bool pv_yield_prev __read_mostly = true; -static bool pv_yield_propagate_owner __read_mostly = true; +static bool pv_yield_sleepy_owner __read_mostly = true; static bool pv_prod_head __read_mostly = false; static DEFINE_PER_CPU_ALIGNED(struct qnodes, qnodes); @@ -247,22 +248,18 @@ static __always_inline void seen_sleepy_lock(void) this_cpu_write(sleepy_lock_seen_clock, sched_clock()); } -static __always_inline void seen_sleepy_node(struct qspinlock *lock, u32 val) +static __always_inline void seen_sleepy_node(void) { if (pv_sleepy_lock) { if (pv_sleepy_lock_interval_ns) this_cpu_write(sleepy_lock_seen_clock, sched_clock()); - if (val & _Q_LOCKED_VAL) { - if (!(val & _Q_SLEEPY_VAL)) - try_set_sleepy(lock, val); - } + /* Don't set sleepy because we likely have a stale val */ } } -static struct qnode *get_tail_qnode(struct qspinlock *lock, u32 val) +static struct qnode *get_tail_qnode(struct qspinlock *lock, int prev_cpu) { - int cpu = decode_tail_cpu(val); - struct qnodes *qnodesp = per_cpu_ptr(&qnodes, cpu); + struct qnodes *qnodesp = per_cpu_ptr(&qnodes, prev_cpu); int idx; /* @@ -353,78 +350,67 @@ static __always_inline bool yield_head_to_locked_owner(struct qspinlock *lock, u return __yield_to_locked_owner(lock, val, paravirt, mustq); } -static __always_inline void propagate_yield_cpu(struct qnode *node, u32 val, int *set_yield_cpu, bool paravirt) +static __always_inline void propagate_sleepy(struct qnode *node, u32 val, bool paravirt) { struct qnode *next; int owner; if (!paravirt) return; - if (!pv_yield_propagate_owner) - return; - - owner = get_owner_cpu(val); - if (*set_yield_cpu == owner) + if (!pv_yield_sleepy_owner) return; next = READ_ONCE(node->next); if (!next) return; - if (vcpu_is_preempted(owner)) { - next->yield_cpu = owner; - *set_yield_cpu = owner; - } else if (*set_yield_cpu != -1) { - next->yield_cpu = owner; - *set_yield_cpu = owner; - } + if (next->sleepy) + return; + + owner = get_owner_cpu(val); + if (vcpu_is_preempted(owner)) + next->sleepy = 1; } /* Called inside spin_begin() */ -static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *node, u32 val, bool paravirt) +static __always_inline bool yield_to_prev(struct qspinlock *lock, struct qnode *node, int prev_cpu, bool paravirt) { - int prev_cpu = decode_tail_cpu(val); u32 yield_count; - int yield_cpu; bool preempted = false; if (!paravirt) goto relax; - if (!pv_yield_propagate_owner) + if (!pv_yield_sleepy_owner) goto yield_prev; - yield_cpu = READ_ONCE(node->yield_cpu); - if (yield_cpu == -1) { - /* Propagate back the -1 CPU */ - if (node->next && node->next->yield_cpu != -1) - node->next->yield_cpu = yield_cpu; - goto yield_prev; + /* + * If the previous waiter was preempted it might not be able to + * propagate sleepy to us, so check the lock in that case too. + */ + if (node->sleepy || vcpu_is_preempted(prev_cpu)) { + u32 val = READ_ONCE(lock->val); + + if (val & _Q_LOCKED_VAL) { + if (node->next && !node->next->sleepy) { + /* + * Propagate sleepy to next waiter. Only if + * owner is preempted, which allows the queue + * to become "non-sleepy" if vCPU preemption + * ceases to occur, even if the lock remains + * highly contended. + */ + if (vcpu_is_preempted(get_owner_cpu(val))) + node->next->sleepy = 1; + } + + preempted = yield_to_locked_owner(lock, val, paravirt); + if (preempted) + return preempted; + } + node->sleepy = false; } - yield_count = yield_count_of(yield_cpu); - if ((yield_count & 1) == 0) - goto yield_prev; /* owner vcpu is running */ - - if (get_owner_cpu(READ_ONCE(lock->val)) != yield_cpu) - goto yield_prev; /* re-sample lock owner */ - - spin_end(); - - preempted = true; - seen_sleepy_node(lock, val); - - smp_rmb(); - - if (yield_cpu == node->yield_cpu) { - if (node->next && node->next->yield_cpu != yield_cpu) - node->next->yield_cpu = yield_cpu; - yield_to_preempted(yield_cpu, yield_count); - spin_begin(); - return preempted; - } - spin_begin(); - yield_prev: if (!pv_yield_prev) goto relax; @@ -436,7 +422,7 @@ yield_prev: spin_end(); preempted = true; - seen_sleepy_node(lock, val); + seen_sleepy_node(); smp_rmb(); /* See __yield_to_locked_owner comment */ @@ -546,7 +532,6 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b bool sleepy = false; bool mustq = false; int idx; - int set_yield_cpu = -1; int iters = 0; BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS)); @@ -570,7 +555,7 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b node->next = NULL; node->lock = lock; node->cpu = smp_processor_id(); - node->yield_cpu = -1; + node->sleepy = 0; node->locked = 0; tail = encode_tail_cpu(node->cpu); @@ -587,7 +572,8 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b * head of the waitqueue. */ if (old & _Q_TAIL_CPU_MASK) { - struct qnode *prev = get_tail_qnode(lock, old); + int prev_cpu = decode_tail_cpu(old); + struct qnode *prev = get_tail_qnode(lock, prev_cpu); /* Link @node into the waitqueue. */ WRITE_ONCE(prev->next, node); @@ -597,16 +583,12 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b while (!READ_ONCE(node->locked)) { spec_barrier(); - if (yield_to_prev(lock, node, old, paravirt)) + if (yield_to_prev(lock, node, prev_cpu, paravirt)) seen_preempted = true; } spec_barrier(); spin_end(); - /* Clear out stale propagated yield_cpu */ - if (paravirt && pv_yield_propagate_owner && node->yield_cpu != -1) - node->yield_cpu = -1; - smp_rmb(); /* acquire barrier for the mcs lock */ /* @@ -648,7 +630,7 @@ again: } } - propagate_yield_cpu(node, val, &set_yield_cpu, paravirt); + propagate_sleepy(node, val, paravirt); preempted = yield_head_to_locked_owner(lock, val, paravirt); if (!maybe_stealers) continue; @@ -952,21 +934,21 @@ static int pv_yield_prev_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(fops_pv_yield_prev, pv_yield_prev_get, pv_yield_prev_set, "%llu\n"); -static int pv_yield_propagate_owner_set(void *data, u64 val) +static int pv_yield_sleepy_owner_set(void *data, u64 val) { - pv_yield_propagate_owner = !!val; + pv_yield_sleepy_owner = !!val; return 0; } -static int pv_yield_propagate_owner_get(void *data, u64 *val) +static int pv_yield_sleepy_owner_get(void *data, u64 *val) { - *val = pv_yield_propagate_owner; + *val = pv_yield_sleepy_owner; return 0; } -DEFINE_SIMPLE_ATTRIBUTE(fops_pv_yield_propagate_owner, pv_yield_propagate_owner_get, pv_yield_propagate_owner_set, "%llu\n"); +DEFINE_SIMPLE_ATTRIBUTE(fops_pv_yield_sleepy_owner, pv_yield_sleepy_owner_get, pv_yield_sleepy_owner_set, "%llu\n"); static int pv_prod_head_set(void *data, u64 val) { @@ -998,7 +980,7 @@ static __init int spinlock_debugfs_init(void) debugfs_create_file("qspl_pv_sleepy_lock_interval_ns", 0600, arch_debugfs_dir, NULL, &fops_pv_sleepy_lock_interval_ns); debugfs_create_file("qspl_pv_sleepy_lock_factor", 0600, arch_debugfs_dir, NULL, &fops_pv_sleepy_lock_factor); debugfs_create_file("qspl_pv_yield_prev", 0600, arch_debugfs_dir, NULL, &fops_pv_yield_prev); - debugfs_create_file("qspl_pv_yield_propagate_owner", 0600, arch_debugfs_dir, NULL, &fops_pv_yield_propagate_owner); + debugfs_create_file("qspl_pv_yield_sleepy_owner", 0600, arch_debugfs_dir, NULL, &fops_pv_yield_sleepy_owner); debugfs_create_file("qspl_pv_prod_head", 0600, arch_debugfs_dir, NULL, &fops_pv_prod_head); } diff --git a/arch/powerpc/mm/book3s32/hash_low.S b/arch/powerpc/mm/book3s32/hash_low.S index 8b804e1a9fa4..4ed0efd03db5 100644 --- a/arch/powerpc/mm/book3s32/hash_low.S +++ b/arch/powerpc/mm/book3s32/hash_low.S @@ -36,8 +36,9 @@ /* * Load a PTE into the hash table, if possible. - * The address is in r4, and r3 contains an access flag: - * _PAGE_RW (0x400) if a write. + * The address is in r4, and r3 contains required access flags: + * - For ISI: _PAGE_PRESENT | _PAGE_EXEC + * - For DSI: _PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE if a write. * r9 contains the SRR1 value, from which we use the MSR_PR bit. * SPRG_THREAD contains the physical address of the current task's thread. * @@ -67,12 +68,16 @@ _GLOBAL(hash_page) lis r0, TASK_SIZE@h /* check if kernel address */ cmplw 0,r4,r0 mfspr r8,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ - ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */ lwz r5,PGDIR(r8) /* virt page-table root */ blt+ 112f /* assume user more likely */ lis r5,swapper_pg_dir@ha /* if kernel address, use */ + andi. r0,r9,MSR_PR /* Check usermode */ addi r5,r5,swapper_pg_dir@l /* kernel page table */ - rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */ +#ifdef CONFIG_SMP + bne- .Lhash_page_out /* return if usermode */ +#else + bnelr- +#endif 112: tophys(r5, r5) #ifndef CONFIG_PTE_64BIT rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */ @@ -113,15 +118,15 @@ _GLOBAL(hash_page) lwarx r6,0,r8 /* get linux-style pte, flag word */ #ifdef CONFIG_PPC_KUAP mfsrin r5,r4 - rlwinm r0,r9,28,_PAGE_RW /* MSR[PR] => _PAGE_RW */ - rlwinm r5,r5,12,_PAGE_RW /* Ks => _PAGE_RW */ + rlwinm r0,r9,28,_PAGE_WRITE /* MSR[PR] => _PAGE_WRITE */ + rlwinm r5,r5,12,_PAGE_WRITE /* Ks => _PAGE_WRITE */ andc r5,r5,r0 /* Ks & ~MSR[PR] */ - andc r5,r6,r5 /* Clear _PAGE_RW when Ks = 1 && MSR[PR] = 0 */ + andc r5,r6,r5 /* Clear _PAGE_WRITE when Ks = 1 && MSR[PR] = 0 */ andc. r5,r3,r5 /* check access & ~permission */ #else andc. r5,r3,r6 /* check access & ~permission */ #endif - rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */ + rlwinm r0,r3,32-3,24,24 /* _PAGE_WRITE access -> _PAGE_DIRTY */ ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE #ifdef CONFIG_SMP bne- .Lhash_page_out /* return if access not permitted */ @@ -307,12 +312,15 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64) __REF _GLOBAL(create_hpte) /* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */ - rlwinm r8,r5,32-9,30,30 /* _PAGE_RW -> PP msb */ + lis r0, TASK_SIZE@h + rlwinm r5,r5,0,~3 /* Clear PP bits */ + cmplw r4,r0 + rlwinm r8,r5,32-9,30,30 /* _PAGE_WRITE -> PP msb */ rlwinm r0,r5,32-6,30,30 /* _PAGE_DIRTY -> PP msb */ and r8,r8,r0 /* writable if _RW & _DIRTY */ - rlwimi r5,r5,32-1,30,30 /* _PAGE_USER -> PP msb */ - rlwimi r5,r5,32-2,31,31 /* _PAGE_USER -> PP lsb */ - ori r8,r8,0xe04 /* clear out reserved bits */ + bge- 1f /* Kernelspace ? Skip */ + ori r5,r5,3 /* Userspace ? PP = 3 */ +1: ori r8,r8,0xe04 /* clear out reserved bits */ andc r8,r5,r8 /* PP = user? (rw&dirty? 1: 3): 0 */ BEGIN_FTR_SECTION rlwinm r8,r8,0,~_PAGE_COHERENT /* clear M (coherence not required) */ diff --git a/arch/powerpc/mm/book3s32/mmu.c b/arch/powerpc/mm/book3s32/mmu.c index 850783cfa9c7..5445587bfe84 100644 --- a/arch/powerpc/mm/book3s32/mmu.c +++ b/arch/powerpc/mm/book3s32/mmu.c @@ -127,7 +127,7 @@ static void setibat(int index, unsigned long virt, phys_addr_t phys, wimgxpp = (flags & _PAGE_COHERENT) | (_PAGE_EXEC ? BPP_RX : BPP_XX); bat[0].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ bat[0].batl = BAT_PHYS_ADDR(phys) | wimgxpp; - if (flags & _PAGE_USER) + if (!is_kernel_addr(virt)) bat[0].batu |= 1; /* Vp = 1 */ } @@ -277,10 +277,10 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys, /* Do DBAT first */ wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | _PAGE_COHERENT | _PAGE_GUARDED); - wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX; + wimgxpp |= (flags & _PAGE_WRITE) ? BPP_RW : BPP_RX; bat[1].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */ bat[1].batl = BAT_PHYS_ADDR(phys) | wimgxpp; - if (flags & _PAGE_USER) + if (!is_kernel_addr(virt)) bat[1].batu |= 1; /* Vp = 1 */ if (flags & _PAGE_GUARDED) { /* G bit must be zero in IBATs */ diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c index 8f8a62d3ff4d..be229290a6a7 100644 --- a/arch/powerpc/mm/book3s64/pgtable.c +++ b/arch/powerpc/mm/book3s64/pgtable.c @@ -635,12 +635,10 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags) unsigned long prot; /* Radix supports execute-only, but protection_map maps X -> RX */ - if (radix_enabled() && ((vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)) { - prot = pgprot_val(PAGE_EXECONLY); - } else { - prot = pgprot_val(protection_map[vm_flags & - (VM_ACCESS_FLAGS | VM_SHARED)]); - } + if (!radix_enabled() && ((vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)) + vm_flags |= VM_READ; + + prot = pgprot_val(protection_map[vm_flags & (VM_ACCESS_FLAGS | VM_SHARED)]); if (vm_flags & VM_SAO) prot |= _PAGE_SAO; diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c index 2369d1bf2411..fde7790277f7 100644 --- a/arch/powerpc/mm/drmem.c +++ b/arch/powerpc/mm/drmem.c @@ -67,7 +67,7 @@ static int drmem_update_dt_v1(struct device_node *memory, struct property *new_prop; struct of_drconf_cell_v1 *dr_cell; struct drmem_lmb *lmb; - u32 *p; + __be32 *p; new_prop = clone_property(prop, prop->length); if (!new_prop) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index b1723094d464..9e49ede2bc1c 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -266,14 +266,15 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma } /* - * VM_READ, VM_WRITE and VM_EXEC all imply read permissions, as - * defined in protection_map[]. Read faults can only be caused by - * a PROT_NONE mapping, or with a PROT_EXEC-only mapping on Radix. + * VM_READ, VM_WRITE and VM_EXEC may imply read permissions, as + * defined in protection_map[]. In that case Read faults can only be + * caused by a PROT_NONE mapping. However a non exec access on a + * VM_EXEC only mapping is invalid anyway, so report it as such. */ if (unlikely(!vma_is_accessible(vma))) return true; - if (unlikely(radix_enabled() && ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC))) + if ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC) return true; /* diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index d8adc452f431..4e71dfe7d026 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -39,6 +39,7 @@ #include #include #include +#include #include diff --git a/arch/powerpc/mm/ioremap.c b/arch/powerpc/mm/ioremap.c index 705e8e8ffde4..7b0afcabd89f 100644 --- a/arch/powerpc/mm/ioremap.c +++ b/arch/powerpc/mm/ioremap.c @@ -50,10 +50,6 @@ void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long flags) if (pte_write(pte)) pte = pte_mkdirty(pte); - /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */ - pte = pte_exprotect(pte); - pte = pte_mkprivileged(pte); - if (iowa_is_active()) return iowa_ioremap(addr, size, pte_pgprot(pte), caller); return __ioremap_caller(addr, size, pte_pgprot(pte), caller); @@ -66,7 +62,7 @@ int early_ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long i; for (i = 0; i < size; i += PAGE_SIZE) { - int err = map_kernel_page(ea + i, pa + i, prot); + int err = map_kernel_page(ea + i, pa + i, pgprot_nx(prot)); if (WARN_ON_ONCE(err)) /* Should clean up */ return err; diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 07e8f4f1e07f..1717554b04b1 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -26,6 +26,7 @@ #include #include #include +#include #include diff --git a/arch/powerpc/mm/nohash/40x.c b/arch/powerpc/mm/nohash/40x.c index 3684d6e570fb..e835e80c09db 100644 --- a/arch/powerpc/mm/nohash/40x.c +++ b/arch/powerpc/mm/nohash/40x.c @@ -48,20 +48,25 @@ */ void __init MMU_init_hw(void) { + int i; + unsigned long zpr; + /* * The Zone Protection Register (ZPR) defines how protection will - * be applied to every page which is a member of a given zone. At - * present, we utilize only two of the 4xx's zones. + * be applied to every page which is a member of a given zone. * The zone index bits (of ZSEL) in the PTE are used for software - * indicators, except the LSB. For user access, zone 1 is used, - * for kernel access, zone 0 is used. We set all but zone 1 - * to zero, allowing only kernel access as indicated in the PTE. - * For zone 1, we set a 01 binary (a value of 10 will not work) + * indicators. We use the 4 upper bits of virtual address to select + * the zone. We set all zones above TASK_SIZE to zero, allowing + * only kernel access as indicated in the PTE. For zones below + * TASK_SIZE, we set a 01 binary (a value of 10 will not work) * to allow user access as indicated in the PTE. This also allows * kernel access as indicated in the PTE. */ - mtspr(SPRN_ZPR, 0x10000000); + for (i = 0, zpr = 0; i < TASK_SIZE >> 28; i++) + zpr |= 1 << (30 - i * 2); + + mtspr(SPRN_ZPR, zpr); flush_instruction_cache(); diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c index a642a7929892..6be6421086ed 100644 --- a/arch/powerpc/mm/nohash/8xx.c +++ b/arch/powerpc/mm/nohash/8xx.c @@ -10,6 +10,8 @@ #include #include +#include + #include #define IMMR_SIZE (FIX_IMMR_SIZE << PAGE_SHIFT) diff --git a/arch/powerpc/mm/nohash/book3e_pgtable.c b/arch/powerpc/mm/nohash/book3e_pgtable.c index b80fc4a91a53..1c5e4ecbebeb 100644 --- a/arch/powerpc/mm/nohash/book3e_pgtable.c +++ b/arch/powerpc/mm/nohash/book3e_pgtable.c @@ -71,7 +71,7 @@ static void __init *early_alloc_pgtable(unsigned long size) * map_kernel_page adds an entry to the ioremap page table * and adds an entry to the HPT, possibly bolting it */ -int __ref map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) +int __ref map_kernel_page(unsigned long ea, phys_addr_t pa, pgprot_t prot) { pgd_t *pgdp; p4d_t *p4dp; diff --git a/arch/powerpc/mm/nohash/e500.c b/arch/powerpc/mm/nohash/e500.c index 40a4e69ae1a9..921c3521ec11 100644 --- a/arch/powerpc/mm/nohash/e500.c +++ b/arch/powerpc/mm/nohash/e500.c @@ -117,15 +117,15 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys, TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0; TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SR; - TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_SW : 0; + TLBCAM[index].MAS3 |= (flags & _PAGE_WRITE) ? MAS3_SW : 0; if (mmu_has_feature(MMU_FTR_BIG_PHYS)) TLBCAM[index].MAS7 = (u64)phys >> 32; /* Below is unlikely -- only for large user pages or similar */ - if (pte_user(__pte(flags))) { + if (!is_kernel_addr(virt)) { TLBCAM[index].MAS3 |= MAS3_UR; TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_UX : 0; - TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_UW : 0; + TLBCAM[index].MAS3 |= (flags & _PAGE_WRITE) ? MAS3_UW : 0; } else { TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_SX : 0; } diff --git a/arch/powerpc/mm/nohash/e500_hugetlbpage.c b/arch/powerpc/mm/nohash/e500_hugetlbpage.c index 6b30e40d4590..a134d28a0e4d 100644 --- a/arch/powerpc/mm/nohash/e500_hugetlbpage.c +++ b/arch/powerpc/mm/nohash/e500_hugetlbpage.c @@ -178,8 +178,7 @@ book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea, pte_t pte) * * This must always be called with the pte lock held. */ -void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, - unsigned long address, pte_t *ptep, unsigned int nr) +void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { if (is_vm_hugetlb_page(vma)) book3e_hugetlb_preload(vma, address, *ptep); diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 4d69bfb9bc11..a04ae4449a02 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -46,13 +46,13 @@ static inline int is_exec_fault(void) * and we avoid _PAGE_SPECIAL and cache inhibited pte. We also only do that * on userspace PTEs */ -static inline int pte_looks_normal(pte_t pte) +static inline int pte_looks_normal(pte_t pte, unsigned long addr) { if (pte_present(pte) && !pte_special(pte)) { if (pte_ci(pte)) return 0; - if (pte_user(pte)) + if (!is_kernel_addr(addr)) return 1; } return 0; @@ -79,11 +79,11 @@ static struct folio *maybe_pte_to_folio(pte_t pte) * support falls into the same category. */ -static pte_t set_pte_filter_hash(pte_t pte) +static pte_t set_pte_filter_hash(pte_t pte, unsigned long addr) { pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); - if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || - cpu_has_feature(CPU_FTR_NOEXECUTE))) { + if (pte_looks_normal(pte, addr) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || + cpu_has_feature(CPU_FTR_NOEXECUTE))) { struct folio *folio = maybe_pte_to_folio(pte); if (!folio) return pte; @@ -97,7 +97,7 @@ static pte_t set_pte_filter_hash(pte_t pte) #else /* CONFIG_PPC_BOOK3S */ -static pte_t set_pte_filter_hash(pte_t pte) { return pte; } +static pte_t set_pte_filter_hash(pte_t pte, unsigned long addr) { return pte; } #endif /* CONFIG_PPC_BOOK3S */ @@ -107,7 +107,7 @@ static pte_t set_pte_filter_hash(pte_t pte) { return pte; } * * This is also called once for the folio. So only work with folio->flags here. */ -static inline pte_t set_pte_filter(pte_t pte) +static inline pte_t set_pte_filter(pte_t pte, unsigned long addr) { struct folio *folio; @@ -115,10 +115,10 @@ static inline pte_t set_pte_filter(pte_t pte) return pte; if (mmu_has_feature(MMU_FTR_HPTE_TABLE)) - return set_pte_filter_hash(pte); + return set_pte_filter_hash(pte, addr); /* No exec permission in the first place, move on */ - if (!pte_exec(pte) || !pte_looks_normal(pte)) + if (!pte_exec(pte) || !pte_looks_normal(pte, addr)) return pte; /* If you set _PAGE_EXEC on weird pages you're on your own */ @@ -198,7 +198,7 @@ void set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep, * is called. Filter the pte value and use the filtered value * to setup all the ptes in the range. */ - pte = set_pte_filter(pte); + pte = set_pte_filter(pte, addr); /* * We don't need to call arch_enter/leave_lazy_mmu_mode() @@ -314,7 +314,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, */ VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep)); - pte = set_pte_filter(pte); + pte = set_pte_filter(pte, addr); val = pte_val(pte); @@ -505,7 +505,7 @@ const pgprot_t protection_map[16] = { [VM_READ] = PAGE_READONLY, [VM_WRITE] = PAGE_COPY, [VM_WRITE | VM_READ] = PAGE_COPY, - [VM_EXEC] = PAGE_READONLY_X, + [VM_EXEC] = PAGE_EXECONLY_X, [VM_EXEC | VM_READ] = PAGE_READONLY_X, [VM_EXEC | VM_WRITE] = PAGE_COPY_X, [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_X, @@ -513,7 +513,7 @@ const pgprot_t protection_map[16] = { [VM_SHARED | VM_READ] = PAGE_READONLY, [VM_SHARED | VM_WRITE] = PAGE_SHARED, [VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED, - [VM_SHARED | VM_EXEC] = PAGE_READONLY_X, + [VM_SHARED | VM_EXEC] = PAGE_EXECONLY_X, [VM_SHARED | VM_EXEC | VM_READ] = PAGE_READONLY_X, [VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_SHARED_X, [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED_X diff --git a/arch/powerpc/mm/ptdump/8xx.c b/arch/powerpc/mm/ptdump/8xx.c index fac932eb8f9a..b5c79b11ea3c 100644 --- a/arch/powerpc/mm/ptdump/8xx.c +++ b/arch/powerpc/mm/ptdump/8xx.c @@ -20,11 +20,6 @@ static const struct flag_info flag_array[] = { #endif .set = "huge", .clear = " ", - }, { - .mask = _PAGE_SH, - .val = 0, - .set = "user", - .clear = " ", }, { .mask = _PAGE_RO | _PAGE_NA, .val = 0, diff --git a/arch/powerpc/mm/ptdump/shared.c b/arch/powerpc/mm/ptdump/shared.c index f884760ca5cf..39c30c62b7ea 100644 --- a/arch/powerpc/mm/ptdump/shared.c +++ b/arch/powerpc/mm/ptdump/shared.c @@ -11,15 +11,15 @@ static const struct flag_info flag_array[] = { { - .mask = _PAGE_USER, - .val = _PAGE_USER, - .set = "user", - .clear = " ", - }, { - .mask = _PAGE_RW, + .mask = _PAGE_READ, .val = 0, - .set = "r ", - .clear = "rw", + .set = " ", + .clear = "r", + }, { + .mask = _PAGE_WRITE, + .val = 0, + .set = " ", + .clear = "w", }, { .mask = _PAGE_EXEC, .val = _PAGE_EXEC, diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 72b7bb34fade..cdea5dccaefe 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -36,9 +36,6 @@ EMIT(PPC_RAW_BRANCH(offset)); \ } while (0) -/* bl (unconditional 'branch' with link) */ -#define PPC_BL(dest) EMIT(PPC_RAW_BL((dest) - (unsigned long)(image + ctx->idx))) - /* "cond" here covers BO:BI fields. */ #define PPC_BCC_SHORT(cond, dest) \ do { \ @@ -147,12 +144,6 @@ struct codegen_context { #define BPF_FIXUP_LEN 2 /* Two instructions => 8 bytes */ #endif -static inline void bpf_flush_icache(void *start, void *end) -{ - smp_wmb(); /* smp write barrier */ - flush_icache_range((unsigned long)start, (unsigned long)end); -} - static inline bool bpf_is_seen_register(struct codegen_context *ctx, int i) { return ctx->seen & (1 << (31 - i)); @@ -169,16 +160,17 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i) } void bpf_jit_init_reg_mapping(struct codegen_context *ctx); -int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func); -int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, +int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func); +int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx, u32 *addrs, int pass, bool extra_pass); void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx); void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx); void bpf_jit_realloc_regs(struct codegen_context *ctx); int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr); -int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx, - int insn_idx, int jmp_off, int dst_reg); +int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass, + struct codegen_context *ctx, int insn_idx, + int jmp_off, int dst_reg); #endif diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 37043dfc1add..0f9a21783329 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -13,9 +13,13 @@ #include #include #include -#include +#include +#include #include +#include +#include + #include "bpf_jit.h" static void bpf_jit_fill_ill_insns(void *area, unsigned int size) @@ -39,10 +43,13 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, return 0; } -struct powerpc64_jit_data { - struct bpf_binary_header *header; +struct powerpc_jit_data { + /* address of rw header */ + struct bpf_binary_header *hdr; + /* address of ro final header */ + struct bpf_binary_header *fhdr; u32 *addrs; - u8 *image; + u8 *fimage; u32 proglen; struct codegen_context ctx; }; @@ -59,15 +66,18 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) u8 *image = NULL; u32 *code_base; u32 *addrs; - struct powerpc64_jit_data *jit_data; + struct powerpc_jit_data *jit_data; struct codegen_context cgctx; int pass; int flen; - struct bpf_binary_header *bpf_hdr; + struct bpf_binary_header *fhdr = NULL; + struct bpf_binary_header *hdr = NULL; struct bpf_prog *org_fp = fp; struct bpf_prog *tmp_fp; bool bpf_blinded = false; bool extra_pass = false; + u8 *fimage = NULL; + u32 *fcode_base; u32 extable_len; u32 fixup_len; @@ -97,9 +107,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) addrs = jit_data->addrs; if (addrs) { cgctx = jit_data->ctx; - image = jit_data->image; - bpf_hdr = jit_data->header; + /* + * JIT compiled to a writable location (image/code_base) first. + * It is then moved to the readonly final location (fimage/fcode_base) + * using instruction patching. + */ + fimage = jit_data->fimage; + fhdr = jit_data->fhdr; proglen = jit_data->proglen; + hdr = jit_data->hdr; + image = (void *)hdr + ((void *)fimage - (void *)fhdr); extra_pass = true; /* During extra pass, ensure index is reset before repopulating extable entries */ cgctx.exentry_idx = 0; @@ -119,7 +136,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) cgctx.stack_size = round_up(fp->aux->stack_depth, 16); /* Scouting faux-generate pass 0 */ - if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) { + if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) { /* We hit something illegal or unsupported. */ fp = org_fp; goto out_addrs; @@ -134,7 +151,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) */ if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) { cgctx.idx = 0; - if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) { + if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) { fp = org_fp; goto out_addrs; } @@ -146,9 +163,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) * update ctgtx.idx as it pretends to output instructions, then we can * calculate total size from idx. */ - bpf_jit_build_prologue(0, &cgctx); + bpf_jit_build_prologue(NULL, &cgctx); addrs[fp->len] = cgctx.idx * 4; - bpf_jit_build_epilogue(0, &cgctx); + bpf_jit_build_epilogue(NULL, &cgctx); fixup_len = fp->aux->num_exentries * BPF_FIXUP_LEN * 4; extable_len = fp->aux->num_exentries * sizeof(struct exception_table_entry); @@ -156,17 +173,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) proglen = cgctx.idx * 4; alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len; - bpf_hdr = bpf_jit_binary_alloc(alloclen, &image, 4, bpf_jit_fill_ill_insns); - if (!bpf_hdr) { + fhdr = bpf_jit_binary_pack_alloc(alloclen, &fimage, 4, &hdr, &image, + bpf_jit_fill_ill_insns); + if (!fhdr) { fp = org_fp; goto out_addrs; } if (extable_len) - fp->aux->extable = (void *)image + FUNCTION_DESCR_SIZE + proglen + fixup_len; + fp->aux->extable = (void *)fimage + FUNCTION_DESCR_SIZE + proglen + fixup_len; skip_init_ctx: code_base = (u32 *)(image + FUNCTION_DESCR_SIZE); + fcode_base = (u32 *)(fimage + FUNCTION_DESCR_SIZE); /* Code generation passes 1-2 */ for (pass = 1; pass < 3; pass++) { @@ -174,8 +193,10 @@ skip_init_ctx: cgctx.idx = 0; cgctx.alt_exit_addr = 0; bpf_jit_build_prologue(code_base, &cgctx); - if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass, extra_pass)) { - bpf_jit_binary_free(bpf_hdr); + if (bpf_jit_build_body(fp, code_base, fcode_base, &cgctx, addrs, pass, + extra_pass)) { + bpf_arch_text_copy(&fhdr->size, &hdr->size, sizeof(hdr->size)); + bpf_jit_binary_pack_free(fhdr, hdr); fp = org_fp; goto out_addrs; } @@ -195,17 +216,19 @@ skip_init_ctx: #ifdef CONFIG_PPC64_ELF_ABI_V1 /* Function descriptor nastiness: Address + TOC */ - ((u64 *)image)[0] = (u64)code_base; + ((u64 *)image)[0] = (u64)fcode_base; ((u64 *)image)[1] = local_paca->kernel_toc; #endif - fp->bpf_func = (void *)image; + fp->bpf_func = (void *)fimage; fp->jited = 1; fp->jited_len = proglen + FUNCTION_DESCR_SIZE; - bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + bpf_hdr->size); if (!fp->is_func || extra_pass) { - bpf_jit_binary_lock_ro(bpf_hdr); + if (bpf_jit_binary_pack_finalize(fp, fhdr, hdr)) { + fp = org_fp; + goto out_addrs; + } bpf_prog_fill_jited_linfo(fp, addrs); out_addrs: kfree(addrs); @@ -215,8 +238,9 @@ out_addrs: jit_data->addrs = addrs; jit_data->ctx = cgctx; jit_data->proglen = proglen; - jit_data->image = image; - jit_data->header = bpf_hdr; + jit_data->fimage = fimage; + jit_data->fhdr = fhdr; + jit_data->hdr = hdr; } out: @@ -230,12 +254,13 @@ out: * The caller should check for (BPF_MODE(code) == BPF_PROBE_MEM) before calling * this function, as this only applies to BPF_PROBE_MEM, for now. */ -int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx, - int insn_idx, int jmp_off, int dst_reg) +int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass, + struct codegen_context *ctx, int insn_idx, int jmp_off, + int dst_reg) { off_t offset; unsigned long pc; - struct exception_table_entry *ex; + struct exception_table_entry *ex, *ex_entry; u32 *fixup; /* Populate extable entries only in the last pass */ @@ -246,9 +271,16 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code WARN_ON_ONCE(ctx->exentry_idx >= fp->aux->num_exentries)) return -EINVAL; + /* + * Program is first written to image before copying to the + * final location (fimage). Accordingly, update in the image first. + * As all offsets used are relative, copying as is to the + * final location should be alright. + */ pc = (unsigned long)&image[insn_idx]; + ex = (void *)fp->aux->extable - (void *)fimage + (void *)image; - fixup = (void *)fp->aux->extable - + fixup = (void *)ex - (fp->aux->num_exentries * BPF_FIXUP_LEN * 4) + (ctx->exentry_idx * BPF_FIXUP_LEN * 4); @@ -259,18 +291,71 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code fixup[BPF_FIXUP_LEN - 1] = PPC_RAW_BRANCH((long)(pc + jmp_off) - (long)&fixup[BPF_FIXUP_LEN - 1]); - ex = &fp->aux->extable[ctx->exentry_idx]; + ex_entry = &ex[ctx->exentry_idx]; - offset = pc - (long)&ex->insn; + offset = pc - (long)&ex_entry->insn; if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN)) return -ERANGE; - ex->insn = offset; + ex_entry->insn = offset; - offset = (long)fixup - (long)&ex->fixup; + offset = (long)fixup - (long)&ex_entry->fixup; if (WARN_ON_ONCE(offset >= 0 || offset < INT_MIN)) return -ERANGE; - ex->fixup = offset; + ex_entry->fixup = offset; ctx->exentry_idx++; return 0; } + +void *bpf_arch_text_copy(void *dst, void *src, size_t len) +{ + int err; + + if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst))) + return ERR_PTR(-EINVAL); + + mutex_lock(&text_mutex); + err = patch_instructions(dst, src, len, false); + mutex_unlock(&text_mutex); + + return err ? ERR_PTR(err) : dst; +} + +int bpf_arch_text_invalidate(void *dst, size_t len) +{ + u32 insn = BREAKPOINT_INSTRUCTION; + int ret; + + if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst))) + return -EINVAL; + + mutex_lock(&text_mutex); + ret = patch_instructions(dst, &insn, len, true); + mutex_unlock(&text_mutex); + + return ret; +} + +void bpf_jit_free(struct bpf_prog *fp) +{ + if (fp->jited) { + struct powerpc_jit_data *jit_data = fp->aux->jit_data; + struct bpf_binary_header *hdr; + + /* + * If we fail the final pass of JIT (from jit_subprogs), + * the program may not be finalized yet. Call finalize here + * before freeing it. + */ + if (jit_data) { + bpf_jit_binary_pack_finalize(fp, jit_data->fhdr, jit_data->hdr); + kvfree(jit_data->addrs); + kfree(jit_data); + } + hdr = bpf_jit_binary_pack_hdr(fp); + bpf_jit_binary_pack_free(hdr, NULL); + WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(fp)); + } + + bpf_prog_unlock_free(fp); +} diff --git a/arch/powerpc/net/bpf_jit_comp32.c b/arch/powerpc/net/bpf_jit_comp32.c index 7f91ea064c08..2f39c50ca729 100644 --- a/arch/powerpc/net/bpf_jit_comp32.c +++ b/arch/powerpc/net/bpf_jit_comp32.c @@ -200,12 +200,13 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) EMIT(PPC_RAW_BLR()); } -int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func) +/* Relative offset needs to be calculated based on final image location */ +int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func) { - s32 rel = (s32)func - (s32)(image + ctx->idx); + s32 rel = (s32)func - (s32)(fimage + ctx->idx); if (image && rel < 0x2000000 && rel >= -0x2000000) { - PPC_BL(func); + EMIT(PPC_RAW_BL(rel)); } else { /* Load function address into r0 */ EMIT(PPC_RAW_LIS(_R0, IMM_H(func))); @@ -278,7 +279,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o } /* Assemble the body code between the prologue & epilogue */ -int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, +int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx, u32 *addrs, int pass, bool extra_pass) { const struct bpf_insn *insn = fp->insnsi; @@ -940,7 +941,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * * !fp->aux->verifier_zext. Emit NOP otherwise. * * Note that "li reg_h,0" is emitted for BPF_B/H/W case, - * if necessary. So, jump there insted of emitting an + * if necessary. So, jump there instead of emitting an * additional "li reg_h,0" instruction. */ if (size == BPF_DW && !fp->aux->verifier_zext) @@ -997,7 +998,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * jmp_off += 4; } - ret = bpf_add_extable_entry(fp, image, pass, ctx, insn_idx, + ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx, insn_idx, jmp_off, dst_reg); if (ret) return ret; @@ -1053,7 +1054,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_5), _R1, 12)); } - ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr); + ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr); if (ret) return ret; diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 0f8048f6dad6..79f23974a320 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -240,7 +240,7 @@ static int bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, u return 0; } -int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func) +int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func) { unsigned int i, ctx_idx = ctx->idx; @@ -361,7 +361,7 @@ asm ( ); /* Assemble the body code between the prologue & epilogue */ -int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, +int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx, u32 *addrs, int pass, bool extra_pass) { enum stf_barrier_type stf_barrier = stf_barrier_type_get(); @@ -940,8 +940,8 @@ emit_clear: addrs[++i] = ctx->idx * 4; if (BPF_MODE(code) == BPF_PROBE_MEM) { - ret = bpf_add_extable_entry(fp, image, pass, ctx, ctx->idx - 1, - 4, dst_reg); + ret = bpf_add_extable_entry(fp, image, fimage, pass, ctx, + ctx->idx - 1, 4, dst_reg); if (ret) return ret; } @@ -995,7 +995,7 @@ emit_clear: if (func_addr_fixed) ret = bpf_jit_emit_func_call_hlp(image, ctx, func_addr); else - ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr); + ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr); if (ret) return ret; diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 8c1f7def596e..10b946e9c6e7 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -1371,8 +1371,7 @@ static void power_pmu_disable(struct pmu *pmu) /* * Disable instruction sampling if it was enabled */ - if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE) - val &= ~MMCRA_SAMPLE_ENABLE; + val &= ~MMCRA_SAMPLE_ENABLE; /* Disable BHRB via mmcra (BHRBRD) for p10 */ if (ppmu->flags & PPMU_ARCH_31) @@ -1383,7 +1382,7 @@ static void power_pmu_disable(struct pmu *pmu) * instruction sampling or BHRB. */ if (val != mmcra) { - mtspr(SPRN_MMCRA, mmcra); + mtspr(SPRN_MMCRA, val); mb(); isync(); } diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index 3449be7c0d51..057ec2e3451d 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c @@ -1338,7 +1338,7 @@ static int get_count_from_result(struct perf_event *event, for (i = count = 0, element_data = res->elements + data_offset; i < num_elements; i++, element_data += data_size + data_offset) - count += be64_to_cpu(*((u64 *) element_data)); + count += be64_to_cpu(*((__be64 *)element_data)); *countp = count; diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index 9d229ef7f86e..5d12ca386c1f 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c @@ -51,7 +51,7 @@ static int trace_imc_mem_size; * core and trace-imc */ static struct imc_pmu_ref imc_global_refc = { - .lock = __SPIN_LOCK_INITIALIZER(imc_global_refc.lock), + .lock = __SPIN_LOCK_UNLOCKED(imc_global_refc.lock), .id = 0, .refc = 0, }; @@ -544,7 +544,7 @@ static int nest_imc_event_init(struct perf_event *event) break; } pcni++; - } while (pcni->vbase != 0); + } while (pcni->vbase); if (!flag) return -ENODEV; @@ -1025,16 +1025,16 @@ static bool is_thread_imc_pmu(struct perf_event *event) return false; } -static u64 * get_event_base_addr(struct perf_event *event) +static __be64 *get_event_base_addr(struct perf_event *event) { u64 addr; if (is_thread_imc_pmu(event)) { addr = (u64)per_cpu(thread_imc_mem, smp_processor_id()); - return (u64 *)(addr + (event->attr.config & IMC_EVENT_OFFSET_MASK)); + return (__be64 *)(addr + (event->attr.config & IMC_EVENT_OFFSET_MASK)); } - return (u64 *)event->hw.event_base; + return (__be64 *)event->hw.event_base; } static void thread_imc_pmu_start_txn(struct pmu *pmu, @@ -1058,7 +1058,8 @@ static int thread_imc_pmu_commit_txn(struct pmu *pmu) static u64 imc_read_counter(struct perf_event *event) { - u64 *addr, data; + __be64 *addr; + u64 data; /* * In-Memory Collection (IMC) counters are free flowing counters. diff --git a/arch/powerpc/perf/power6-pmu.c b/arch/powerpc/perf/power6-pmu.c index 5729b6e059de..9f720b522e17 100644 --- a/arch/powerpc/perf/power6-pmu.c +++ b/arch/powerpc/perf/power6-pmu.c @@ -335,26 +335,38 @@ static const unsigned int event_alternatives[][MAX_ALT] = { { 0x3000fe, 0x400056 }, /* PM_DATA_FROM_L3MISS */ }; -/* - * This could be made more efficient with a binary search on - * a presorted list, if necessary - */ static int find_alternatives_list(u64 event) { - int i, j; - unsigned int alt; + const unsigned int presorted_event_table[] = { + 0x0130e8, 0x080080, 0x080088, 0x10000a, 0x10000b, 0x10000d, 0x10000e, + 0x100010, 0x10001a, 0x100026, 0x100054, 0x100056, 0x1000f0, 0x1000f8, + 0x1000fc, 0x200008, 0x20000e, 0x200010, 0x200012, 0x200054, 0x2000f0, + 0x2000f2, 0x2000f4, 0x2000f5, 0x2000f6, 0x2000f8, 0x2000fc, 0x2000fe, + 0x2d0030, 0x30000a, 0x30000c, 0x300010, 0x300012, 0x30001a, 0x300056, + 0x3000f0, 0x3000f2, 0x3000f6, 0x3000f8, 0x3000fc, 0x3000fe, 0x400006, + 0x400007, 0x40000a, 0x40000e, 0x400010, 0x400018, 0x400056, 0x4000f0, + 0x4000f8, 0x600005 + }; + const unsigned int event_index_table[] = { + 0, 1, 2, 3, 4, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 12, 14, + 7, 15, 2, 9, 16, 3, 4, 0, 17, 10, 18, 19, 20, 1, 17, 15, 19, + 18, 2, 16, 21, 8, 0, 22, 13, 14, 11, 21, 5, 20, 22, 1, 6, 3 + }; + int hi = ARRAY_SIZE(presorted_event_table) - 1; + int lo = 0; - for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) { - if (event < event_alternatives[i][0]) - return -1; - for (j = 0; j < MAX_ALT; ++j) { - alt = event_alternatives[i][j]; - if (!alt || event < alt) - break; - if (event == alt) - return i; - } + while (lo <= hi) { + int mid = lo + (hi - lo) / 2; + unsigned int alt = presorted_event_table[mid]; + + if (alt < event) + lo = mid + 1; + else if (alt > event) + hi = mid - 1; + else + return event_index_table[mid]; } + return -1; } diff --git a/arch/powerpc/platforms/4xx/soc.c b/arch/powerpc/platforms/4xx/soc.c index b2d940437a66..5412e6b21e10 100644 --- a/arch/powerpc/platforms/4xx/soc.c +++ b/arch/powerpc/platforms/4xx/soc.c @@ -112,7 +112,7 @@ static int __init ppc4xx_l2c_probe(void) } /* Install error handler */ - if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) { + if (request_irq(irq, l2c_error_handler, 0, "L2C", NULL) < 0) { printk(KERN_ERR "Cannot install L2C error handler" ", cache is not enabled\n"); of_node_put(np); diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c index 2fb2a85d131f..1135c1ab923c 100644 --- a/arch/powerpc/platforms/83xx/misc.c +++ b/arch/powerpc/platforms/83xx/misc.c @@ -14,6 +14,8 @@ #include #include #include +#include + #include #include diff --git a/arch/powerpc/platforms/8xx/cpm1.c b/arch/powerpc/platforms/8xx/cpm1.c index ebb5f6a27dbf..b24d4102fbf6 100644 --- a/arch/powerpc/platforms/8xx/cpm1.c +++ b/arch/powerpc/platforms/8xx/cpm1.c @@ -40,6 +40,7 @@ #include #include #include +#include #include diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c index 77ea9335fd04..f381b177ea06 100644 --- a/arch/powerpc/platforms/book3s/vas-api.c +++ b/arch/powerpc/platforms/book3s/vas-api.c @@ -4,6 +4,8 @@ * Copyright (C) 2019 Haren Myneni, IBM Corp */ +#define pr_fmt(fmt) "vas-api: " fmt + #include #include #include @@ -78,7 +80,7 @@ int get_vas_user_win_ref(struct vas_user_win_ref *task_ref) task_ref->mm = get_task_mm(current); if (!task_ref->mm) { put_pid(task_ref->pid); - pr_err("VAS: pid(%d): mm_struct is not found\n", + pr_err("pid(%d): mm_struct is not found\n", current->pid); return -EPERM; } @@ -235,8 +237,7 @@ void vas_update_csb(struct coprocessor_request_block *crb, rc = kill_pid_info(SIGSEGV, &info, pid); rcu_read_unlock(); - pr_devel("%s(): pid %d kill_proc_info() rc %d\n", __func__, - pid_vnr(pid), rc); + pr_devel("pid %d kill_proc_info() rc %d\n", pid_vnr(pid), rc); } void vas_dump_crb(struct coprocessor_request_block *crb) @@ -294,7 +295,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) rc = copy_from_user(&uattr, uptr, sizeof(uattr)); if (rc) { - pr_err("%s(): copy_from_user() returns %d\n", __func__, rc); + pr_err("copy_from_user() returns %d\n", rc); return -EFAULT; } @@ -311,7 +312,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg) txwin = cp_inst->coproc->vops->open_win(uattr.vas_id, uattr.flags, cp_inst->coproc->cop_type); if (IS_ERR(txwin)) { - pr_err("%s() VAS window open failed, %ld\n", __func__, + pr_err_ratelimited("VAS window open failed rc=%ld\n", PTR_ERR(txwin)); return PTR_ERR(txwin); } @@ -405,8 +406,7 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf) * window is not opened. Shouldn't expect this error. */ if (!cp_inst || !cp_inst->txwin) { - pr_err("%s(): Unexpected fault on paste address with TX window closed\n", - __func__); + pr_err("Unexpected fault on paste address with TX window closed\n"); return VM_FAULT_SIGBUS; } @@ -421,8 +421,7 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf) * issue NX request. */ if (txwin->task_ref.vma != vmf->vma) { - pr_err("%s(): No previous mapping with paste address\n", - __func__); + pr_err("No previous mapping with paste address\n"); return VM_FAULT_SIGBUS; } @@ -481,19 +480,19 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) txwin = cp_inst->txwin; if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) { - pr_debug("%s(): size 0x%zx, PAGE_SIZE 0x%zx\n", __func__, + pr_debug("size 0x%zx, PAGE_SIZE 0x%zx\n", (vma->vm_end - vma->vm_start), PAGE_SIZE); return -EINVAL; } /* Ensure instance has an open send window */ if (!txwin) { - pr_err("%s(): No send window open?\n", __func__); + pr_err("No send window open?\n"); return -EINVAL; } if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->paste_addr) { - pr_err("%s(): VAS API is not registered\n", __func__); + pr_err("VAS API is not registered\n"); return -EACCES; } @@ -510,14 +509,14 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) */ mutex_lock(&txwin->task_ref.mmap_mutex); if (txwin->status != VAS_WIN_ACTIVE) { - pr_err("%s(): Window is not active\n", __func__); + pr_err("Window is not active\n"); rc = -EACCES; goto out; } paste_addr = cp_inst->coproc->vops->paste_addr(txwin); if (!paste_addr) { - pr_err("%s(): Window paste address failed\n", __func__); + pr_err("Window paste address failed\n"); rc = -EINVAL; goto out; } @@ -533,8 +532,8 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) rc = remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff, vma->vm_end - vma->vm_start, prot); - pr_devel("%s(): paste addr %llx at %lx, rc %d\n", __func__, - paste_addr, vma->vm_start, rc); + pr_devel("paste addr %llx at %lx, rc %d\n", paste_addr, + vma->vm_start, rc); txwin->task_ref.vma = vma; vma->vm_ops = &vas_vm_ops; @@ -609,8 +608,7 @@ int vas_register_coproc_api(struct module *mod, enum vas_cop_type cop_type, goto err; } - pr_devel("%s: Added dev [%d,%d]\n", __func__, MAJOR(devno), - MINOR(devno)); + pr_devel("Added dev [%d,%d]\n", MAJOR(devno), MINOR(devno)); return 0; diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig index 130707ec9f99..8bdae0caf21e 100644 --- a/arch/powerpc/platforms/powermac/Kconfig +++ b/arch/powerpc/platforms/powermac/Kconfig @@ -2,6 +2,7 @@ config PPC_PMAC bool "Apple PowerMac based machines" depends on PPC_BOOK3S && CPU_BIG_ENDIAN + select ADB_CUDA if POWER_RESET && PPC32 select MPIC select FORCE_PCI select PPC_INDIRECT_PCI if PPC32 diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index ae62d432db8b..81c9fbae88b1 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2614,7 +2614,8 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ struct device_node* node; int i; volatile u32 __iomem *base; - const u32 *addrp, *revp; + const __be32 *addrp; + const u32 *revp; phys_addr_t addr; u64 size; diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 40f3aa432fba..c097d591670e 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -925,8 +925,10 @@ static void __init smu_i2c_probe(void) sz = sizeof(struct pmac_i2c_bus) + sizeof(struct smu_i2c_cmd); bus = kzalloc(sz, GFP_KERNEL); - if (bus == NULL) + if (bus == NULL) { + of_node_put(busnode); return; + } bus->controller = controller; bus->busnode = of_node_get(busnode); diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 8be71920e63c..c83d1e14077e 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -598,8 +598,10 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) name = "Pulsar"; break; } - if (pmac_tb_freeze != NULL) + if (pmac_tb_freeze != NULL) { + of_node_put(cc); break; + } } if (pmac_tb_freeze != NULL) { /* Open i2c bus for synchronous access */ diff --git a/arch/powerpc/platforms/powernv/opal-fadump.h b/arch/powerpc/platforms/powernv/opal-fadump.h index 3f715efb0aa6..5eeb794b5eb1 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.h +++ b/arch/powerpc/platforms/powernv/opal-fadump.h @@ -135,7 +135,7 @@ static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt, for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) { reg_entry = (struct hdat_fadump_reg_entry *)bufp; val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) : - (u64)(reg_entry->reg_val)); + (u64 __force)(reg_entry->reg_val)); opal_fadump_set_regval_regnum(regs, be32_to_cpu(reg_entry->reg_type), be32_to_cpu(reg_entry->reg_num), diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index aa4042dcd6d4..a43bfb01720a 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -55,7 +55,8 @@ static bool find_aa_index(struct device_node *dr_node, struct property *ala_prop, const u32 *lmb_assoc, u32 *aa_index) { - u32 *assoc_arrays, new_prop_size; + __be32 *assoc_arrays; + u32 new_prop_size; struct property *new_prop; int aa_arrays, aa_array_entries, aa_array_sz; int i, index; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 16d93b580f61..496e16c588aa 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -914,7 +914,8 @@ static int remove_ddw(struct device_node *np, bool remove_prop, const char *win_ return 0; } -static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift) +static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *window_shift, + bool *direct_mapping) { struct dma_win *window; const struct dynamic_dma_window_prop *dma64; @@ -927,6 +928,7 @@ static bool find_existing_ddw(struct device_node *pdn, u64 *dma_addr, int *windo dma64 = window->prop; *dma_addr = be64_to_cpu(dma64->dma_base); *window_shift = be32_to_cpu(dma64->window_shift); + *direct_mapping = window->direct; found = true; break; } @@ -1270,10 +1272,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn) mutex_lock(&dma_win_init_mutex); - if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len)) { - direct_mapping = (len >= max_ram_len); + if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len, &direct_mapping)) goto out_unlock; - } /* * If we already went through this for a previous function of diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index f2cb62148f36..4561667832ed 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -192,9 +192,9 @@ static void free_dtl_buffers(unsigned long *time_limit) continue; kmem_cache_free(dtl_cache, pp->dispatch_log); pp->dtl_ridx = 0; - pp->dispatch_log = 0; - pp->dispatch_log_end = 0; - pp->dtl_curr = 0; + pp->dispatch_log = NULL; + pp->dispatch_log_end = NULL; + pp->dtl_curr = NULL; if (time_limit && time_after(jiffies, *time_limit)) { cond_resched(); @@ -223,7 +223,7 @@ static void destroy_cpu_associativity(void) { kfree(vcpu_associativity); kfree(pcpu_associativity); - vcpu_associativity = pcpu_associativity = 0; + vcpu_associativity = pcpu_associativity = NULL; } static __be32 *__get_cpu_associativity(int cpu, __be32 *cpu_assoc, int flag) @@ -526,8 +526,10 @@ static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p, if (cmd) { rc = init_cpu_associativity(); - if (rc) + if (rc) { + destroy_cpu_associativity(); goto out; + } for_each_possible_cpu(cpu) { disp = per_cpu_ptr(&vcpu_disp_data, cpu); diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c index 2d40304eb6c1..febe18f251d0 100644 --- a/arch/powerpc/platforms/pseries/plpks.c +++ b/arch/powerpc/platforms/pseries/plpks.c @@ -150,7 +150,7 @@ static int plpks_gen_password(void) ospasswordlength = maxpwsize; ospassword = kzalloc(maxpwsize, GFP_KERNEL); if (!ospassword) { - kfree(password); + kfree_sensitive(password); return -ENOMEM; } memcpy(ospassword, password, ospasswordlength); @@ -163,7 +163,7 @@ static int plpks_gen_password(void) } } out: - kfree(password); + kfree_sensitive(password); return pseries_status_to_err(rc); } diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c index e25ac52acf50..b1f25bac280b 100644 --- a/arch/powerpc/platforms/pseries/vas.c +++ b/arch/powerpc/platforms/pseries/vas.c @@ -341,7 +341,7 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags, if (atomic_inc_return(&cop_feat_caps->nr_used_credits) > atomic_read(&cop_feat_caps->nr_total_credits)) { - pr_err("Credits are not available to allocate window\n"); + pr_err_ratelimited("Credits are not available to allocate window\n"); rc = -EINVAL; goto out; } @@ -424,7 +424,7 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags, put_vas_user_win_ref(&txwin->vas_win.task_ref); rc = -EBUSY; - pr_err("No credit is available to allocate window\n"); + pr_err_ratelimited("No credit is available to allocate window\n"); out_free: /* diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 57978a44d55b..558ec68d768e 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -11,9 +11,11 @@ #include #include #include +#include #include #include -#include +#include +#include #include #include #include @@ -392,7 +394,6 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev, static const struct of_device_id fsl_of_msi_ids[]; static int fsl_of_msi_probe(struct platform_device *dev) { - const struct of_device_id *match; struct fsl_msi *msi; struct resource res, msiir; int err, i, j, irq_index, count; @@ -402,10 +403,7 @@ static int fsl_of_msi_probe(struct platform_device *dev) u32 offset; struct pci_controller *phb; - match = of_match_device(fsl_of_msi_ids, &dev->dev); - if (!match) - return -EINVAL; - features = match->data; + features = device_get_match_data(&dev->dev); printk(KERN_DEBUG "Setting up Freescale MSI support\n"); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index ba287abcb008..dabbdd356664 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -355,7 +355,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK); r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0)); - if (r == le32_to_cpu(MPIC_VECPRI_MASK)) { + if (r == swab32(MPIC_VECPRI_MASK)) { printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); mpic->flags |= MPIC_BROKEN_IPI; } diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 9f0af4d795d8..f1c0fa6ece21 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c @@ -802,7 +802,7 @@ int xive_native_get_queue_info(u32 vp_id, u32 prio, if (out_qpage) *out_qpage = be64_to_cpu(qpage); if (out_qsize) - *out_qsize = be32_to_cpu(qsize); + *out_qsize = be64_to_cpu(qsize); if (out_qeoi_page) *out_qeoi_page = be64_to_cpu(qeoi_page); if (out_escalate_irq) diff --git a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh index a31a56016c09..73e331e7660e 100755 --- a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh +++ b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh @@ -7,21 +7,20 @@ set -o pipefail # To debug, uncomment the following line # set -x -# -mprofile-kernel is only supported on 64-bit, so this should not be invoked -# for 32-bit. We pass in -m64 explicitly, and -mbig-endian and -mlittle-endian -# are passed in from Kconfig, which takes care of toolchains defaulting to -# other targets. +# -mprofile-kernel is only supported on 64-bit with ELFv2, so this should not +# be invoked for other targets. Therefore we can pass in -m64 and -mabi +# explicitly, to take care of toolchains defaulting to other targets. # Test whether the compile option -mprofile-kernel exists and generates # profiling code (ie. a call to _mcount()). echo "int func() { return 0; }" | \ - $* -m64 -S -x c -O2 -p -mprofile-kernel - -o - \ + $* -m64 -mabi=elfv2 -S -x c -O2 -p -mprofile-kernel - -o - \ 2> /dev/null | grep -q "_mcount" # Test whether the notrace attribute correctly suppresses calls to _mcount(). echo -e "#include \nnotrace int func() { return 0; }" | \ - $* -m64 -S -x c -O2 -p -mprofile-kernel - -o - \ + $* -m64 -mabi=elfv2 -S -x c -O2 -p -mprofile-kernel - -o - \ 2> /dev/null | grep -q "_mcount" && \ exit 1 diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ae29e4392664..b0d67ac8695f 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -131,6 +131,7 @@ config S390 select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP select BUILDTIME_TABLE_SORT select CLONE_BACKWARDS2 + select DCACHE_WORD_ACCESS if !KMSAN select DMA_OPS if PCI select DYNAMIC_FTRACE if FUNCTION_TRACER select FUNCTION_ALIGNMENT_8B if CC_IS_GCC diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index d3e48bd9c394..8826c4f18645 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -49,7 +49,7 @@ static void detect_facilities(void) { if (test_facility(8)) { machine.has_edat1 = 1; - __ctl_set_bit(0, 23); + local_ctl_set_bit(0, CR0_EDAT_BIT); } if (test_facility(78)) machine.has_edat2 = 1; diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c index 442a74f113cb..3075d65e112c 100644 --- a/arch/s390/boot/vmem.c +++ b/arch/s390/boot/vmem.c @@ -5,13 +5,14 @@ #include #include #include +#include #include #include #include #include "decompressor.h" #include "boot.h" -unsigned long __bootdata_preserved(s390_invalid_asce); +struct ctlreg __bootdata_preserved(s390_invalid_asce); #ifdef CONFIG_PROC_FS atomic_long_t __bootdata_preserved(direct_pages_count[PG_DIRECT_MAP_MAX]); @@ -166,8 +167,6 @@ static bool kasan_pmd_populate_zero_shadow(pmd_t *pmd, unsigned long addr, static bool kasan_pte_populate_zero_shadow(pte_t *pte, enum populate_mode mode) { - pte_t entry; - if (mode == POPULATE_KASAN_ZERO_SHADOW) { set_pte(pte, pte_z); return true; @@ -426,7 +425,7 @@ void setup_vmem(unsigned long asce_limit) asce_type = _REGION3_ENTRY_EMPTY; asce_bits = _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH; } - s390_invalid_asce = invalid_pg_dir | _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH; + s390_invalid_asce.val = invalid_pg_dir | _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH; crst_table_init((unsigned long *)swapper_pg_dir, asce_type); crst_table_init((unsigned long *)invalid_pg_dir, _REGION3_ENTRY_EMPTY); @@ -447,12 +446,12 @@ void setup_vmem(unsigned long asce_limit) kasan_populate_shadow(); - S390_lowcore.kernel_asce = swapper_pg_dir | asce_bits; + S390_lowcore.kernel_asce.val = swapper_pg_dir | asce_bits; S390_lowcore.user_asce = s390_invalid_asce; - __ctl_load(S390_lowcore.kernel_asce, 1, 1); - __ctl_load(S390_lowcore.user_asce, 7, 7); - __ctl_load(S390_lowcore.kernel_asce, 13, 13); + local_ctl_load(1, &S390_lowcore.kernel_asce); + local_ctl_load(7, &S390_lowcore.user_asce); + local_ctl_load(13, &S390_lowcore.kernel_asce); - init_mm.context.asce = S390_lowcore.kernel_asce; + init_mm.context.asce = S390_lowcore.kernel_asce.val; } diff --git a/arch/s390/include/asm/asm-extable.h b/arch/s390/include/asm/asm-extable.h index e6532477f126..4a6b0a8b6412 100644 --- a/arch/s390/include/asm/asm-extable.h +++ b/arch/s390/include/asm/asm-extable.h @@ -13,6 +13,7 @@ #define EX_TYPE_UA_LOAD_MEM 4 #define EX_TYPE_UA_LOAD_REG 5 #define EX_TYPE_UA_LOAD_REGPAIR 6 +#define EX_TYPE_ZEROPAD 7 #define EX_DATA_REG_ERR_SHIFT 0 #define EX_DATA_REG_ERR GENMASK(3, 0) @@ -23,16 +24,7 @@ #define EX_DATA_LEN_SHIFT 8 #define EX_DATA_LEN GENMASK(11, 8) -#define __EX_TABLE(_section, _fault, _target, _type) \ - stringify_in_c(.section _section,"a";) \ - stringify_in_c(.balign 4;) \ - stringify_in_c(.long (_fault) - .;) \ - stringify_in_c(.long (_target) - .;) \ - stringify_in_c(.short (_type);) \ - stringify_in_c(.short 0;) \ - stringify_in_c(.previous) - -#define __EX_TABLE_UA(_section, _fault, _target, _type, _regerr, _regaddr, _len)\ +#define __EX_TABLE(_section, _fault, _target, _type, _regerr, _regaddr, _len) \ stringify_in_c(.section _section,"a";) \ stringify_in_c(.balign 4;) \ stringify_in_c(.long (_fault) - .;) \ @@ -72,21 +64,24 @@ stringify_in_c(.previous) #define EX_TABLE(_fault, _target) \ - __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP) + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_FIXUP, __stringify(%%r0), __stringify(%%r0), 0) #define EX_TABLE_AMODE31(_fault, _target) \ - __EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP) + __EX_TABLE(.amode31.ex_table, _fault, _target, EX_TYPE_FIXUP, __stringify(%%r0), __stringify(%%r0), 0) #define EX_TABLE_UA_STORE(_fault, _target, _regerr) \ - __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_STORE, _regerr, _regerr, 0) + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_STORE, _regerr, _regerr, 0) #define EX_TABLE_UA_LOAD_MEM(_fault, _target, _regerr, _regmem, _len) \ - __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_MEM, _regerr, _regmem, _len) + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_MEM, _regerr, _regmem, _len) #define EX_TABLE_UA_LOAD_REG(_fault, _target, _regerr, _regzero) \ - __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REG, _regerr, _regzero, 0) + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REG, _regerr, _regzero, 0) #define EX_TABLE_UA_LOAD_REGPAIR(_fault, _target, _regerr, _regzero) \ - __EX_TABLE_UA(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0) + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_UA_LOAD_REGPAIR, _regerr, _regzero, 0) + +#define EX_TABLE_ZEROPAD(_fault, _target, _regdata, _regaddr) \ + __EX_TABLE(__ex_table, _fault, _target, EX_TYPE_ZEROPAD, _regdata, _regaddr, 0) #endif /* __ASM_EXTABLE_H */ diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h deleted file mode 100644 index adf7d8cdac7e..000000000000 --- a/arch/s390/include/asm/ctl_reg.h +++ /dev/null @@ -1,146 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright IBM Corp. 1999, 2009 - * - * Author(s): Martin Schwidefsky - */ - -#ifndef __ASM_CTL_REG_H -#define __ASM_CTL_REG_H - -#include - -#define CR0_CLOCK_COMPARATOR_SIGN BIT(63 - 10) -#define CR0_LOW_ADDRESS_PROTECTION BIT(63 - 35) -#define CR0_FETCH_PROTECTION_OVERRIDE BIT(63 - 38) -#define CR0_STORAGE_PROTECTION_OVERRIDE BIT(63 - 39) -#define CR0_EMERGENCY_SIGNAL_SUBMASK BIT(63 - 49) -#define CR0_EXTERNAL_CALL_SUBMASK BIT(63 - 50) -#define CR0_CLOCK_COMPARATOR_SUBMASK BIT(63 - 52) -#define CR0_CPU_TIMER_SUBMASK BIT(63 - 53) -#define CR0_SERVICE_SIGNAL_SUBMASK BIT(63 - 54) -#define CR0_UNUSED_56 BIT(63 - 56) -#define CR0_INTERRUPT_KEY_SUBMASK BIT(63 - 57) -#define CR0_MEASUREMENT_ALERT_SUBMASK BIT(63 - 58) - -#define CR14_UNUSED_32 BIT(63 - 32) -#define CR14_UNUSED_33 BIT(63 - 33) -#define CR14_CHANNEL_REPORT_SUBMASK BIT(63 - 35) -#define CR14_RECOVERY_SUBMASK BIT(63 - 36) -#define CR14_DEGRADATION_SUBMASK BIT(63 - 37) -#define CR14_EXTERNAL_DAMAGE_SUBMASK BIT(63 - 38) -#define CR14_WARNING_SUBMASK BIT(63 - 39) - -#ifndef __ASSEMBLY__ - -#include - -#define __ctl_load(array, low, high) do { \ - typedef struct { char _[sizeof(array)]; } addrtype; \ - \ - BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\ - asm volatile( \ - " lctlg %1,%2,%0\n" \ - : \ - : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high) \ - : "memory"); \ -} while (0) - -#define __ctl_store(array, low, high) do { \ - typedef struct { char _[sizeof(array)]; } addrtype; \ - \ - BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\ - asm volatile( \ - " stctg %1,%2,%0\n" \ - : "=Q" (*(addrtype *)(&array)) \ - : "i" (low), "i" (high)); \ -} while (0) - -static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit) -{ - unsigned long reg; - - __ctl_store(reg, cr, cr); - reg |= 1UL << bit; - __ctl_load(reg, cr, cr); -} - -static __always_inline void __ctl_clear_bit(unsigned int cr, unsigned int bit) -{ - unsigned long reg; - - __ctl_store(reg, cr, cr); - reg &= ~(1UL << bit); - __ctl_load(reg, cr, cr); -} - -void smp_ctl_set_clear_bit(int cr, int bit, bool set); - -static inline void ctl_set_bit(int cr, int bit) -{ - smp_ctl_set_clear_bit(cr, bit, true); -} - -static inline void ctl_clear_bit(int cr, int bit) -{ - smp_ctl_set_clear_bit(cr, bit, false); -} - -union ctlreg0 { - unsigned long val; - struct { - unsigned long : 8; - unsigned long tcx : 1; /* Transactional-Execution control */ - unsigned long pifo : 1; /* Transactional-Execution Program- - Interruption-Filtering Override */ - unsigned long : 3; - unsigned long ccc : 1; /* Cryptography counter control */ - unsigned long pec : 1; /* PAI extension control */ - unsigned long : 17; - unsigned long : 3; - unsigned long lap : 1; /* Low-address-protection control */ - unsigned long : 4; - unsigned long edat : 1; /* Enhanced-DAT-enablement control */ - unsigned long : 2; - unsigned long iep : 1; /* Instruction-Execution-Protection */ - unsigned long : 1; - unsigned long afp : 1; /* AFP-register control */ - unsigned long vx : 1; /* Vector enablement control */ - unsigned long : 7; - unsigned long sssm : 1; /* Service signal subclass mask */ - unsigned long : 9; - }; -}; - -union ctlreg2 { - unsigned long val; - struct { - unsigned long : 33; - unsigned long ducto : 25; - unsigned long : 1; - unsigned long gse : 1; - unsigned long : 1; - unsigned long tds : 1; - unsigned long tdc : 2; - }; -}; - -union ctlreg5 { - unsigned long val; - struct { - unsigned long : 33; - unsigned long pasteo: 25; - unsigned long : 6; - }; -}; - -union ctlreg15 { - unsigned long val; - struct { - unsigned long lsea : 61; - unsigned long : 3; - }; -}; - -#endif /* __ASSEMBLY__ */ -#endif /* __ASM_CTL_REG_H */ diff --git a/arch/s390/include/asm/ctlreg.h b/arch/s390/include/asm/ctlreg.h new file mode 100644 index 000000000000..6d4b85f2b541 --- /dev/null +++ b/arch/s390/include/asm/ctlreg.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright IBM Corp. 1999, 2009 + * + * Author(s): Martin Schwidefsky + */ + +#ifndef __ASM_S390_CTLREG_H +#define __ASM_S390_CTLREG_H + +#include + +#define CR0_TRANSACTIONAL_EXECUTION_BIT (63 - 8) +#define CR0_CLOCK_COMPARATOR_SIGN_BIT (63 - 10) +#define CR0_CRYPTOGRAPHY_COUNTER_BIT (63 - 13) +#define CR0_PAI_EXTENSION_BIT (63 - 14) +#define CR0_CPUMF_EXTRACTION_AUTH_BIT (63 - 15) +#define CR0_WARNING_TRACK_BIT (63 - 30) +#define CR0_LOW_ADDRESS_PROTECTION_BIT (63 - 35) +#define CR0_FETCH_PROTECTION_OVERRIDE_BIT (63 - 38) +#define CR0_STORAGE_PROTECTION_OVERRIDE_BIT (63 - 39) +#define CR0_EDAT_BIT (63 - 40) +#define CR0_INSTRUCTION_EXEC_PROTECTION_BIT (63 - 43) +#define CR0_VECTOR_BIT (63 - 46) +#define CR0_MALFUNCTION_ALERT_SUBMASK_BIT (63 - 48) +#define CR0_EMERGENCY_SIGNAL_SUBMASK_BIT (63 - 49) +#define CR0_EXTERNAL_CALL_SUBMASK_BIT (63 - 50) +#define CR0_CLOCK_COMPARATOR_SUBMASK_BIT (63 - 52) +#define CR0_CPU_TIMER_SUBMASK_BIT (63 - 53) +#define CR0_SERVICE_SIGNAL_SUBMASK_BIT (63 - 54) +#define CR0_UNUSED_56_BIT (63 - 56) +#define CR0_INTERRUPT_KEY_SUBMASK_BIT (63 - 57) +#define CR0_MEASUREMENT_ALERT_SUBMASK_BIT (63 - 58) +#define CR0_ETR_SUBMASK_BIT (63 - 59) +#define CR0_IUCV_BIT (63 - 62) + +#define CR0_TRANSACTIONAL_EXECUTION BIT(CR0_TRANSACTIONAL_EXECUTION_BIT) +#define CR0_CLOCK_COMPARATOR_SIGN BIT(CR0_CLOCK_COMPARATOR_SIGN_BIT) +#define CR0_CRYPTOGRAPHY_COUNTER BIT(CR0_CRYPTOGRAPHY_COUNTER_BIT) +#define CR0_PAI_EXTENSION BIT(CR0_PAI_EXTENSION_BIT) +#define CR0_CPUMF_EXTRACTION_AUTH BIT(CR0_CPUMF_EXTRACTION_AUTH_BIT) +#define CR0_WARNING_TRACK BIT(CR0_WARNING_TRACK_BIT) +#define CR0_LOW_ADDRESS_PROTECTION BIT(CR0_LOW_ADDRESS_PROTECTION_BIT) +#define CR0_FETCH_PROTECTION_OVERRIDE BIT(CR0_FETCH_PROTECTION_OVERRIDE_BIT) +#define CR0_STORAGE_PROTECTION_OVERRIDE BIT(CR0_STORAGE_PROTECTION_OVERRIDE_BIT) +#define CR0_EDAT BIT(CR0_EDAT_BIT) +#define CR0_INSTRUCTION_EXEC_PROTECTION BIT(CR0_INSTRUCTION_EXEC_PROTECTION_BIT) +#define CR0_VECTOR BIT(CR0_VECTOR_BIT) +#define CR0_MALFUNCTION_ALERT_SUBMASK BIT(CR0_MALFUNCTION_ALERT_SUBMASK_BIT) +#define CR0_EMERGENCY_SIGNAL_SUBMASK BIT(CR0_EMERGENCY_SIGNAL_SUBMASK_BIT) +#define CR0_EXTERNAL_CALL_SUBMASK BIT(CR0_EXTERNAL_CALL_SUBMASK_BIT) +#define CR0_CLOCK_COMPARATOR_SUBMASK BIT(CR0_CLOCK_COMPARATOR_SUBMASK_BIT) +#define CR0_CPU_TIMER_SUBMASK BIT(CR0_CPU_TIMER_SUBMASK_BIT) +#define CR0_SERVICE_SIGNAL_SUBMASK BIT(CR0_SERVICE_SIGNAL_SUBMASK_BIT) +#define CR0_UNUSED_56 BIT(CR0_UNUSED_56_BIT) +#define CR0_INTERRUPT_KEY_SUBMASK BIT(CR0_INTERRUPT_KEY_SUBMASK_BIT) +#define CR0_MEASUREMENT_ALERT_SUBMASK BIT(CR0_MEASUREMENT_ALERT_SUBMASK_BIT) +#define CR0_ETR_SUBMASK BIT(CR0_ETR_SUBMASK_BIT) +#define CR0_IUCV BIT(CR0_IUCV_BIT) + +#define CR2_MIO_ADDRESSING_BIT (63 - 58) +#define CR2_GUARDED_STORAGE_BIT (63 - 59) + +#define CR2_MIO_ADDRESSING BIT(CR2_MIO_ADDRESSING_BIT) +#define CR2_GUARDED_STORAGE BIT(CR2_GUARDED_STORAGE_BIT) + +#define CR14_UNUSED_32_BIT (63 - 32) +#define CR14_UNUSED_33_BIT (63 - 33) +#define CR14_CHANNEL_REPORT_SUBMASK_BIT (63 - 35) +#define CR14_RECOVERY_SUBMASK_BIT (63 - 36) +#define CR14_DEGRADATION_SUBMASK_BIT (63 - 37) +#define CR14_EXTERNAL_DAMAGE_SUBMASK_BIT (63 - 38) +#define CR14_WARNING_SUBMASK_BIT (63 - 39) + +#define CR14_UNUSED_32 BIT(CR14_UNUSED_32_BIT) +#define CR14_UNUSED_33 BIT(CR14_UNUSED_33_BIT) +#define CR14_CHANNEL_REPORT_SUBMASK BIT(CR14_CHANNEL_REPORT_SUBMASK_BIT) +#define CR14_RECOVERY_SUBMASK BIT(CR14_RECOVERY_SUBMASK_BIT) +#define CR14_DEGRADATION_SUBMASK BIT(CR14_DEGRADATION_SUBMASK_BIT) +#define CR14_EXTERNAL_DAMAGE_SUBMASK BIT(CR14_EXTERNAL_DAMAGE_SUBMASK_BIT) +#define CR14_WARNING_SUBMASK BIT(CR14_WARNING_SUBMASK_BIT) + +#ifndef __ASSEMBLY__ + +#include + +struct ctlreg { + unsigned long val; +}; + +#define __local_ctl_load(low, high, array) do { \ + struct addrtype { \ + char _[sizeof(array)]; \ + }; \ + int _high = high; \ + int _low = low; \ + int _esize; \ + \ + _esize = (_high - _low + 1) * sizeof(struct ctlreg); \ + BUILD_BUG_ON(sizeof(struct addrtype) != _esize); \ + typecheck(struct ctlreg, array[0]); \ + asm volatile( \ + " lctlg %[_low],%[_high],%[_arr]\n" \ + : \ + : [_arr] "Q" (*(struct addrtype *)(&array)), \ + [_low] "i" (low), [_high] "i" (high) \ + : "memory"); \ +} while (0) + +#define __local_ctl_store(low, high, array) do { \ + struct addrtype { \ + char _[sizeof(array)]; \ + }; \ + int _high = high; \ + int _low = low; \ + int _esize; \ + \ + _esize = (_high - _low + 1) * sizeof(struct ctlreg); \ + BUILD_BUG_ON(sizeof(struct addrtype) != _esize); \ + typecheck(struct ctlreg, array[0]); \ + asm volatile( \ + " stctg %[_low],%[_high],%[_arr]\n" \ + : [_arr] "=Q" (*(struct addrtype *)(&array)) \ + : [_low] "i" (low), [_high] "i" (high)); \ +} while (0) + +static __always_inline void local_ctl_load(unsigned int cr, struct ctlreg *reg) +{ + asm volatile( + " lctlg %[cr],%[cr],%[reg]\n" + : + : [reg] "Q" (*reg), [cr] "i" (cr) + : "memory"); +} + +static __always_inline void local_ctl_store(unsigned int cr, struct ctlreg *reg) +{ + asm volatile( + " stctg %[cr],%[cr],%[reg]\n" + : [reg] "=Q" (*reg) + : [cr] "i" (cr)); +} + +static __always_inline void local_ctl_set_bit(unsigned int cr, unsigned int bit) +{ + struct ctlreg reg; + + local_ctl_store(cr, ®); + reg.val |= 1UL << bit; + local_ctl_load(cr, ®); +} + +static __always_inline void local_ctl_clear_bit(unsigned int cr, unsigned int bit) +{ + struct ctlreg reg; + + local_ctl_store(cr, ®); + reg.val &= ~(1UL << bit); + local_ctl_load(cr, ®); +} + +struct lowcore; + +void system_ctlreg_lock(void); +void system_ctlreg_unlock(void); +void system_ctlreg_init_save_area(struct lowcore *lc); +void system_ctlreg_modify(unsigned int cr, unsigned long data, int request); + +enum { + CTLREG_SET_BIT, + CTLREG_CLEAR_BIT, + CTLREG_LOAD, +}; + +static inline void system_ctl_set_bit(unsigned int cr, unsigned int bit) +{ + system_ctlreg_modify(cr, bit, CTLREG_SET_BIT); +} + +static inline void system_ctl_clear_bit(unsigned int cr, unsigned int bit) +{ + system_ctlreg_modify(cr, bit, CTLREG_CLEAR_BIT); +} + +static inline void system_ctl_load(unsigned int cr, struct ctlreg *reg) +{ + system_ctlreg_modify(cr, reg->val, CTLREG_LOAD); +} + +union ctlreg0 { + unsigned long val; + struct ctlreg reg; + struct { + unsigned long : 8; + unsigned long tcx : 1; /* Transactional-Execution control */ + unsigned long pifo : 1; /* Transactional-Execution Program- + Interruption-Filtering Override */ + unsigned long : 3; + unsigned long ccc : 1; /* Cryptography counter control */ + unsigned long pec : 1; /* PAI extension control */ + unsigned long : 17; + unsigned long : 3; + unsigned long lap : 1; /* Low-address-protection control */ + unsigned long : 4; + unsigned long edat : 1; /* Enhanced-DAT-enablement control */ + unsigned long : 2; + unsigned long iep : 1; /* Instruction-Execution-Protection */ + unsigned long : 1; + unsigned long afp : 1; /* AFP-register control */ + unsigned long vx : 1; /* Vector enablement control */ + unsigned long : 7; + unsigned long sssm : 1; /* Service signal subclass mask */ + unsigned long : 9; + }; +}; + +union ctlreg2 { + unsigned long val; + struct ctlreg reg; + struct { + unsigned long : 33; + unsigned long ducto : 25; + unsigned long : 1; + unsigned long gse : 1; + unsigned long : 1; + unsigned long tds : 1; + unsigned long tdc : 2; + }; +}; + +union ctlreg5 { + unsigned long val; + struct ctlreg reg; + struct { + unsigned long : 33; + unsigned long pasteo: 25; + unsigned long : 6; + }; +}; + +union ctlreg15 { + unsigned long val; + struct ctlreg reg; + struct { + unsigned long lsea : 61; + unsigned long : 3; + }; +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_S390_CTLREG_H */ diff --git a/arch/s390/include/asm/fault.h b/arch/s390/include/asm/fault.h new file mode 100644 index 000000000000..d326f56603d6 --- /dev/null +++ b/arch/s390/include/asm/fault.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright IBM Corp. 1999, 2023 + */ +#ifndef _ASM_S390_FAULT_H +#define _ASM_S390_FAULT_H + +union teid { + unsigned long val; + struct { + unsigned long addr : 52; /* Translation-exception Address */ + unsigned long fsi : 2; /* Access Exception Fetch/Store Indication */ + unsigned long : 2; + unsigned long b56 : 1; + unsigned long : 3; + unsigned long b60 : 1; + unsigned long b61 : 1; + unsigned long as : 2; /* ASCE Identifier */ + }; +}; + +enum { + TEID_FSI_UNKNOWN = 0, /* Unknown whether fetch or store */ + TEID_FSI_STORE = 1, /* Exception was due to store operation */ + TEID_FSI_FETCH = 2 /* Exception was due to fetch operation */ +}; + +#endif /* _ASM_S390_FAULT_H */ diff --git a/arch/s390/include/asm/fpu/internal.h b/arch/s390/include/asm/fpu/internal.h index bbdadb1c9efc..8634581b9011 100644 --- a/arch/s390/include/asm/fpu/internal.h +++ b/arch/s390/include/asm/fpu/internal.h @@ -10,7 +10,6 @@ #define _ASM_S390_FPU_INTERNAL_H #include -#include #include static inline void save_vx_regs(__vector128 *vxrs) diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 89902f754740..54b42817f70a 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h @@ -31,6 +31,7 @@ #include #include #include +#include enum interruption_class { IRQEXT_CLK, @@ -101,17 +102,17 @@ enum irq_subclass { }; #define CR0_IRQ_SUBCLASS_MASK \ - ((1UL << (63 - 30)) /* Warning Track */ | \ - (1UL << (63 - 48)) /* Malfunction Alert */ | \ - (1UL << (63 - 49)) /* Emergency Signal */ | \ - (1UL << (63 - 50)) /* External Call */ | \ - (1UL << (63 - 52)) /* Clock Comparator */ | \ - (1UL << (63 - 53)) /* CPU Timer */ | \ - (1UL << (63 - 54)) /* Service Signal */ | \ - (1UL << (63 - 57)) /* Interrupt Key */ | \ - (1UL << (63 - 58)) /* Measurement Alert */ | \ - (1UL << (63 - 59)) /* Timing Alert */ | \ - (1UL << (63 - 62))) /* IUCV */ + (CR0_WARNING_TRACK | \ + CR0_MALFUNCTION_ALERT_SUBMASK | \ + CR0_EMERGENCY_SIGNAL_SUBMASK | \ + CR0_EXTERNAL_CALL_SUBMASK | \ + CR0_CLOCK_COMPARATOR_SUBMASK | \ + CR0_CPU_TIMER_SUBMASK | \ + CR0_SERVICE_SIGNAL_SUBMASK | \ + CR0_INTERRUPT_KEY_SUBMASK | \ + CR0_MEASUREMENT_ALERT_SUBMASK | \ + CR0_ETR_SUBMASK | \ + CR0_IUCV) void irq_subclass_register(enum irq_subclass subclass); void irq_subclass_unregister(enum irq_subclass subclass); diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h index 83f732ca3af4..21b9e5290c04 100644 --- a/arch/s390/include/asm/kprobes.h +++ b/arch/s390/include/asm/kprobes.h @@ -15,6 +15,7 @@ * */ #include +#include #include #define BREAKPOINT_INSTRUCTION 0x0002 @@ -65,7 +66,7 @@ struct prev_kprobe { struct kprobe_ctlblk { unsigned long kprobe_status; unsigned long kprobe_saved_imask; - unsigned long kprobe_saved_ctl[3]; + struct ctlreg kprobe_saved_ctl[3]; struct prev_kprobe prev_kprobe; }; diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 69ccc464a430..5dc1b6345006 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -139,8 +140,8 @@ struct lowcore { __u32 restart_flags; /* 0x0384 */ /* Address space pointer. */ - __u64 kernel_asce; /* 0x0388 */ - __u64 user_asce; /* 0x0390 */ + struct ctlreg kernel_asce; /* 0x0388 */ + struct ctlreg user_asce; /* 0x0390 */ /* * The lpp and current_pid fields form a @@ -199,7 +200,7 @@ struct lowcore { __u32 clock_comp_save_area[2]; /* 0x1330 */ __u64 last_break_save_area; /* 0x1338 */ __u32 access_regs_save_area[16]; /* 0x1340 */ - __u64 cregs_save_area[16]; /* 0x1380 */ + struct ctlreg cregs_save_area[16]; /* 0x1380 */ __u8 pad_0x1400[0x1500-0x1400]; /* 0x1400 */ /* Cryptography-counter designation */ __u64 ccd; /* 0x1500 */ @@ -221,12 +222,4 @@ static inline void set_prefix(__u32 address) asm volatile("spx %0" : : "Q" (address) : "memory"); } -static inline __u32 store_prefix(void) -{ - __u32 address; - - asm volatile("stpx %0" : "=Q" (address)); - return address; -} - #endif /* _ASM_S390_LOWCORE_H */ diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 2a38af5a00c2..757fe6f0d802 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #define init_new_context init_new_context @@ -78,10 +78,10 @@ static inline void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct * if (next == &init_mm) S390_lowcore.user_asce = s390_invalid_asce; else - S390_lowcore.user_asce = next->context.asce; + S390_lowcore.user_asce.val = next->context.asce; cpumask_set_cpu(cpu, &next->context.cpu_attach_mask); /* Clear previous user-ASCE from CR7 */ - __ctl_load(s390_invalid_asce, 7, 7); + local_ctl_load(7, &s390_invalid_asce); if (prev != next) cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask); } @@ -111,7 +111,7 @@ static inline void finish_arch_post_lock_switch(void) __tlb_flush_mm_lazy(mm); preempt_enable(); } - __ctl_load(S390_lowcore.user_asce, 7, 7); + local_ctl_load(7, &S390_lowcore.user_asce); } #define activate_mm activate_mm @@ -120,7 +120,7 @@ static inline void activate_mm(struct mm_struct *prev, { switch_mm(prev, next, current); cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); - __ctl_load(S390_lowcore.user_asce, 7, 7); + local_ctl_load(7, &S390_lowcore.user_asce); } #include diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index fb3ee7758b76..601e87fa8a9a 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,7 @@ extern pgd_t swapper_pg_dir[]; extern pgd_t invalid_pg_dir[]; extern void paging_init(void); -extern unsigned long s390_invalid_asce; +extern struct ctlreg s390_invalid_asce; enum { PG_DIRECT_MAP_4K = 0, diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index 73ed2781073b..6e5b1b4b19a9 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -59,7 +59,6 @@ static inline void smp_cpus_done(unsigned int max_cpus) { } -extern int smp_reinit_ipl_cpu(void); extern int smp_rescan_cpus(void); extern void __noreturn cpu_die(void); extern void __cpu_die(unsigned int cpu); diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 8a8c64a678c4..81ae8a98e7ec 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -15,7 +15,6 @@ */ #include #include -#include #include #include #include diff --git a/arch/s390/include/asm/word-at-a-time.h b/arch/s390/include/asm/word-at-a-time.h new file mode 100644 index 000000000000..2579f1694b82 --- /dev/null +++ b/arch/s390/include/asm/word-at-a-time.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_WORD_AT_A_TIME_H +#define _ASM_WORD_AT_A_TIME_H + +#include +#include +#include + +struct word_at_a_time { + const unsigned long bits; +}; + +#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x7f) } + +static inline unsigned long prep_zero_mask(unsigned long val, unsigned long data, const struct word_at_a_time *c) +{ + return data; +} + +static inline unsigned long create_zero_mask(unsigned long data) +{ + return __fls(data); +} + +static inline unsigned long find_zero(unsigned long data) +{ + return (data ^ (BITS_PER_LONG - 1)) >> 3; +} + +static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) +{ + unsigned long mask = (val & c->bits) + c->bits; + + *data = ~(mask | val | c->bits); + return *data; +} + +static inline unsigned long zero_bytemask(unsigned long data) +{ + return ~1UL << data; +} + +/* + * Load an unaligned word from kernel space. + * + * In the (very unlikely) case of the word being a page-crosser + * and the next page not being mapped, take the exception and + * return zeroes in the non-existing part. + */ +static inline unsigned long load_unaligned_zeropad(const void *addr) +{ + unsigned long data; + + asm volatile( + "0: lg %[data],0(%[addr])\n" + "1: nopr %%r7\n" + EX_TABLE_ZEROPAD(0b, 1b, %[data], %[addr]) + EX_TABLE_ZEROPAD(1b, 1b, %[data], %[addr]) + : [data] "=d" (data) + : [addr] "a" (addr), "m" (*(unsigned long *)addr)); + return data; +} + +#endif /* _ASM_WORD_AT_A_TIME_H */ diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 0df2b88cc0da..353def93973b 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -37,7 +37,7 @@ CFLAGS_unwind_bc.o += -fno-optimize-sibling-calls obj-y := head64.o traps.o time.o process.o earlypgm.o early.o setup.o idle.o vtime.o obj-y += processor.o syscall.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o cpufeature.o -obj-y += sysinfo.o lgr.o os_info.o +obj-y += sysinfo.o lgr.o os_info.o ctlreg.o obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o obj-y += entry.o reipl.o kdebugfs.o alternative.o obj-y += nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index 7af69948b290..514feadd4c58 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -498,7 +498,7 @@ static int get_mem_chunk_cnt(void) /* * Initialize ELF loads (new kernel) */ -static void loads_init(Elf64_Phdr *phdr, u64 loads_offset) +static void loads_init(Elf64_Phdr *phdr) { phys_addr_t start, end; u64 idx; @@ -507,7 +507,7 @@ static void loads_init(Elf64_Phdr *phdr, u64 loads_offset) phdr->p_filesz = end - start; phdr->p_type = PT_LOAD; phdr->p_offset = start; - phdr->p_vaddr = start; + phdr->p_vaddr = (unsigned long)__va(start); phdr->p_paddr = start; phdr->p_memsz = end - start; phdr->p_flags = PF_R | PF_W | PF_X; @@ -612,7 +612,7 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) ptr = notes_init(phdr_notes, ptr, ((unsigned long) hdr) + hdr_off); /* Init loads */ hdr_off = PTR_DIFF(ptr, hdr); - loads_init(phdr_loads, hdr_off); + loads_init(phdr_loads); *addr = (unsigned long long) hdr; *size = (unsigned long long) hdr_off; BUG_ON(elfcorehdr_size > alloc_size); diff --git a/arch/s390/kernel/ctlreg.c b/arch/s390/kernel/ctlreg.c new file mode 100644 index 000000000000..8cc26cf2c64a --- /dev/null +++ b/arch/s390/kernel/ctlreg.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright IBM Corp. 1999, 2023 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * ctl_lock guards access to global control register contents which + * are kept in the control register save area within absolute lowcore + * at physical address zero. + */ +static DEFINE_SPINLOCK(system_ctl_lock); + +void system_ctlreg_lock(void) + __acquires(&system_ctl_lock) +{ + spin_lock(&system_ctl_lock); +} + +void system_ctlreg_unlock(void) + __releases(&system_ctl_lock) +{ + spin_unlock(&system_ctl_lock); +} + +static bool system_ctlreg_area_init __ro_after_init; + +void __init system_ctlreg_init_save_area(struct lowcore *lc) +{ + struct lowcore *abs_lc; + + abs_lc = get_abs_lowcore(); + __local_ctl_store(0, 15, lc->cregs_save_area); + __local_ctl_store(0, 15, abs_lc->cregs_save_area); + put_abs_lowcore(abs_lc); + system_ctlreg_area_init = true; +} + +struct ctlreg_parms { + unsigned long andval; + unsigned long orval; + unsigned long val; + int request; + int cr; +}; + +static void ctlreg_callback(void *info) +{ + struct ctlreg_parms *pp = info; + struct ctlreg regs[16]; + + __local_ctl_store(0, 15, regs); + if (pp->request == CTLREG_LOAD) { + regs[pp->cr].val = pp->val; + } else { + regs[pp->cr].val &= pp->andval; + regs[pp->cr].val |= pp->orval; + } + __local_ctl_load(0, 15, regs); +} + +static void system_ctlreg_update(void *info) +{ + unsigned long flags; + + if (system_state == SYSTEM_BOOTING) { + /* + * For very early calls do not call on_each_cpu() + * since not everything might be setup. + */ + local_irq_save(flags); + ctlreg_callback(info); + local_irq_restore(flags); + } else { + on_each_cpu(ctlreg_callback, info, 1); + } +} + +void system_ctlreg_modify(unsigned int cr, unsigned long data, int request) +{ + struct ctlreg_parms pp = { .cr = cr, .request = request, }; + struct lowcore *abs_lc; + + switch (request) { + case CTLREG_SET_BIT: + pp.orval = 1UL << data; + pp.andval = -1UL; + break; + case CTLREG_CLEAR_BIT: + pp.orval = 0; + pp.andval = ~(1UL << data); + break; + case CTLREG_LOAD: + pp.val = data; + break; + } + if (system_ctlreg_area_init) { + system_ctlreg_lock(); + abs_lc = get_abs_lowcore(); + if (request == CTLREG_LOAD) { + abs_lc->cregs_save_area[cr].val = pp.val; + } else { + abs_lc->cregs_save_area[cr].val &= pp.andval; + abs_lc->cregs_save_area[cr].val |= pp.orval; + } + put_abs_lowcore(abs_lc); + system_ctlreg_update(&pp); + system_ctlreg_unlock(); + } else { + system_ctlreg_update(&pp); + } +} +EXPORT_SYMBOL(system_ctlreg_modify); diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c index f9f06cd8fcee..92fdc35f028c 100644 --- a/arch/s390/kernel/diag.c +++ b/arch/s390/kernel/diag.c @@ -245,6 +245,7 @@ EXPORT_SYMBOL(diag8c); int diag224(void *ptr) { + unsigned long addr = __pa(ptr); int rc = -EOPNOTSUPP; diag_stat_inc(DIAG_STAT_X224); @@ -253,7 +254,7 @@ int diag224(void *ptr) "0: lhi %0,0x0\n" "1:\n" EX_TABLE(0b,1b) - : "+d" (rc) :"d" (0), "d" (ptr) : "memory"); + : "+d" (rc) :"d" (0), "d" (addr) : "memory"); return rc; } EXPORT_SYMBOL(diag224); diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 442ce0489e1a..ff1f02b54771 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -216,7 +216,7 @@ static __init void detect_machine_facilities(void) { if (test_facility(8)) { S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1; - __ctl_set_bit(0, 23); + system_ctl_set_bit(0, CR0_EDAT_BIT); } if (test_facility(78)) S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2; @@ -224,13 +224,13 @@ static __init void detect_machine_facilities(void) S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; if (test_facility(50) && test_facility(73)) { S390_lowcore.machine_flags |= MACHINE_FLAG_TE; - __ctl_set_bit(0, 55); + system_ctl_set_bit(0, CR0_TRANSACTIONAL_EXECUTION_BIT); } if (test_facility(51)) S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; if (test_facility(129)) { S390_lowcore.machine_flags |= MACHINE_FLAG_VX; - __ctl_set_bit(0, 17); + system_ctl_set_bit(0, CR0_VECTOR_BIT); } if (test_facility(130)) S390_lowcore.machine_flags |= MACHINE_FLAG_NX; @@ -240,7 +240,7 @@ static __init void detect_machine_facilities(void) /* Enabled signed clock comparator comparisons */ S390_lowcore.machine_flags |= MACHINE_FLAG_SCC; clock_comparator_max = -1ULL >> 1; - __ctl_set_bit(0, 53); + system_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SIGN_BIT); } if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) { S390_lowcore.machine_flags |= MACHINE_FLAG_PCI_MIO; @@ -258,15 +258,9 @@ static inline void save_vector_registers(void) #endif } -static inline void setup_control_registers(void) +static inline void setup_low_address_protection(void) { - unsigned long reg; - - __ctl_store(reg, 0, 0); - reg |= CR0_LOW_ADDRESS_PROTECTION; - reg |= CR0_EMERGENCY_SIGNAL_SUBMASK; - reg |= CR0_EXTERNAL_CALL_SUBMASK; - __ctl_load(reg, 0, 0); + system_ctl_set_bit(0, CR0_LOW_ADDRESS_PROTECTION_BIT); } static inline void setup_access_registers(void) @@ -279,7 +273,7 @@ static inline void setup_access_registers(void) static int __init disable_vector_extension(char *str) { S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; - __ctl_clear_bit(0, 17); + system_ctl_clear_bit(0, CR0_VECTOR_BIT); return 0; } early_param("novx", disable_vector_extension); @@ -314,7 +308,7 @@ void __init startup_init(void) save_vector_registers(); setup_topology(); sclp_early_detect(); - setup_control_registers(); + setup_low_address_protection(); setup_access_registers(); lockdep_on(); } diff --git a/arch/s390/kernel/guarded_storage.c b/arch/s390/kernel/guarded_storage.c index d14dd1c2e524..0b68168d9566 100644 --- a/arch/s390/kernel/guarded_storage.c +++ b/arch/s390/kernel/guarded_storage.c @@ -28,7 +28,7 @@ static int gs_enable(void) return -ENOMEM; gs_cb->gsd = 25; preempt_disable(); - __ctl_set_bit(2, 4); + local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); load_gs_cb(gs_cb); current->thread.gs_cb = gs_cb; preempt_enable(); @@ -42,7 +42,7 @@ static int gs_disable(void) preempt_disable(); kfree(current->thread.gs_cb); current->thread.gs_cb = NULL; - __ctl_clear_bit(2, 4); + local_ctl_clear_bit(2, CR2_GUARDED_STORAGE_BIT); preempt_enable(); } return 0; @@ -84,7 +84,7 @@ void gs_load_bc_cb(struct pt_regs *regs) if (gs_cb) { kfree(current->thread.gs_cb); current->thread.gs_bc_cb = NULL; - __ctl_set_bit(2, 4); + local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); load_gs_cb(gs_cb); current->thread.gs_cb = gs_cb; } diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 05e51666db03..cc364fce6aa9 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -2381,7 +2381,7 @@ void s390_reset_system(void) set_prefix(0); /* Disable lowcore protection */ - __ctl_clear_bit(0, 28); + local_ctl_clear_bit(0, CR0_LOW_ADDRESS_PROTECTION_BIT); diag_amode31_ops.diag308_reset(); } diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index b020ff17d206..6f71b0ce1068 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -385,7 +385,7 @@ void irq_subclass_register(enum irq_subclass subclass) { spin_lock(&irq_subclass_lock); if (!irq_subclass_refcount[subclass]) - ctl_set_bit(0, subclass); + system_ctl_set_bit(0, subclass); irq_subclass_refcount[subclass]++; spin_unlock(&irq_subclass_lock); } @@ -396,7 +396,7 @@ void irq_subclass_unregister(enum irq_subclass subclass) spin_lock(&irq_subclass_lock); irq_subclass_refcount[subclass]--; if (!irq_subclass_refcount[subclass]) - ctl_clear_bit(0, subclass); + system_ctl_clear_bit(0, subclass); spin_unlock(&irq_subclass_lock); } EXPORT_SYMBOL(irq_subclass_unregister); diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index d4b863ed0aa7..f0cf20d4b3c5 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -224,20 +224,27 @@ static void enable_singlestep(struct kprobe_ctlblk *kcb, struct pt_regs *regs, unsigned long ip) { - struct per_regs per_kprobe; + union { + struct ctlreg regs[3]; + struct { + struct ctlreg control; + struct ctlreg start; + struct ctlreg end; + }; + } per_kprobe; /* Set up the PER control registers %cr9-%cr11 */ - per_kprobe.control = PER_EVENT_IFETCH; - per_kprobe.start = ip; - per_kprobe.end = ip; + per_kprobe.control.val = PER_EVENT_IFETCH; + per_kprobe.start.val = ip; + per_kprobe.end.val = ip; /* Save control regs and psw mask */ - __ctl_store(kcb->kprobe_saved_ctl, 9, 11); + __local_ctl_store(9, 11, kcb->kprobe_saved_ctl); kcb->kprobe_saved_imask = regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT); /* Set PER control regs, turns on single step for the given address */ - __ctl_load(per_kprobe, 9, 11); + __local_ctl_load(9, 11, per_kprobe.regs); regs->psw.mask |= PSW_MASK_PER; regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); regs->psw.addr = ip; @@ -249,7 +256,7 @@ static void disable_singlestep(struct kprobe_ctlblk *kcb, unsigned long ip) { /* Restore control regs and psw mask, set new psw address */ - __ctl_load(kcb->kprobe_saved_ctl, 9, 11); + __local_ctl_load(9, 11, kcb->kprobe_saved_ctl); regs->psw.mask &= ~PSW_MASK_PER; regs->psw.mask |= kcb->kprobe_saved_imask; regs->psw.addr = ip; diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index ce65fc01671f..bb0d4d68fcbe 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -94,12 +94,12 @@ static noinline void __machine_kdump(void *image) if (MACHINE_HAS_VX) save_vx_regs((__vector128 *) mcesa->vector_save_area); if (MACHINE_HAS_GS) { - __ctl_store(cr2_old.val, 2, 2); + local_ctl_store(2, &cr2_old.reg); cr2_new = cr2_old; cr2_new.gse = 1; - __ctl_load(cr2_new.val, 2, 2); + local_ctl_load(2, &cr2_new.reg); save_gs_cb((struct gs_cb *) mcesa->guarded_storage_save_area); - __ctl_load(cr2_old.val, 2, 2); + local_ctl_load(2, &cr2_old.reg); } /* * To create a good backchain for this CPU in the dump store_status diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 38ec0487521c..0daf0f1cdfc9 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -22,13 +22,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -131,10 +131,10 @@ static notrace void s390_handle_damage(void) * Disable low address protection and make machine check new PSW a * disabled wait PSW. Any additional machine check cannot be handled. */ - __ctl_store(cr0.val, 0, 0); + local_ctl_store(0, &cr0.reg); cr0_new = cr0; cr0_new.lap = 0; - __ctl_load(cr0_new.val, 0, 0); + local_ctl_load(0, &cr0_new.reg); psw_save = S390_lowcore.mcck_new_psw; psw_bits(S390_lowcore.mcck_new_psw).io = 0; psw_bits(S390_lowcore.mcck_new_psw).ext = 0; @@ -146,7 +146,7 @@ static notrace void s390_handle_damage(void) * values. This makes possible system dump analysis easier. */ S390_lowcore.mcck_new_psw = psw_save; - __ctl_load(cr0.val, 0, 0); + local_ctl_load(0, &cr0.reg); disabled_wait(); while (1); } @@ -185,7 +185,7 @@ void s390_handle_mcck(void) static int mchchk_wng_posted = 0; /* Use single cpu clear, as we cannot handle smp here. */ - __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ + local_ctl_clear_bit(14, CR14_WARNING_SUBMASK_BIT); if (xchg(&mchchk_wng_posted, 1) == 0) kill_cad_pid(SIGPWR, 1); } @@ -269,9 +269,9 @@ static int notrace s390_validate_registers(union mci mci) */ if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST)) kill_task = 1; - cr0.val = S390_lowcore.cregs_save_area[0]; + cr0.reg = S390_lowcore.cregs_save_area[0]; cr0.afp = cr0.vx = 1; - __ctl_load(cr0.val, 0, 0); + local_ctl_load(0, &cr0.reg); asm volatile( " la 1,%0\n" " VLM 0,15,0,1\n" @@ -279,7 +279,7 @@ static int notrace s390_validate_registers(union mci mci) : : "Q" (*(struct vx_array *)mcesa->vector_save_area) : "1"); - __ctl_load(S390_lowcore.cregs_save_area[0], 0, 0); + local_ctl_load(0, &S390_lowcore.cregs_save_area[0]); } /* Validate access registers */ asm volatile( @@ -290,7 +290,7 @@ static int notrace s390_validate_registers(union mci mci) if (!mci.ar) kill_task = 1; /* Validate guarded storage registers */ - cr2.val = S390_lowcore.cregs_save_area[2]; + cr2.reg = S390_lowcore.cregs_save_area[2]; if (cr2.gse) { if (!mci.gs) { /* @@ -505,9 +505,9 @@ NOKPROBE_SYMBOL(s390_do_machine_check); static int __init machine_check_init(void) { - ctl_set_bit(14, 25); /* enable external damage MCH */ - ctl_set_bit(14, 27); /* enable system recovery MCH */ - ctl_set_bit(14, 24); /* enable warning MCH */ + system_ctl_set_bit(14, CR14_EXTERNAL_DAMAGE_SUBMASK_BIT); + system_ctl_set_bit(14, CR14_RECOVERY_SUBMASK_BIT); + system_ctl_set_bit(14, CR14_WARNING_SUBMASK_BIT); return 0; } early_initcall(machine_check_init); diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 850c11ea631a..41ed6e0f0a2a 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -1193,7 +1193,7 @@ static int __init cpumf_pmu_init(void) * Clear bit 15 of cr0 to unauthorize problem-state to * extract measurement counters */ - ctl_clear_bit(0, 48); + system_ctl_clear_bit(0, CR0_CPUMF_EXTRACTION_AUTH_BIT); /* register handler for measurement-alert interruptions */ rc = register_external_irq(EXT_IRQ_MEASURE_ALERT, diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index fe7d1774ded1..77fd24e6cbb6 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -16,8 +16,7 @@ #include #include #include - -#include +#include #include #include @@ -41,7 +40,43 @@ struct paicrypt_map { struct perf_event *event; /* Perf event for sampling */ }; -static DEFINE_PER_CPU(struct paicrypt_map, paicrypt_map); +struct paicrypt_mapptr { + struct paicrypt_map *mapptr; +}; + +static struct paicrypt_root { /* Anchor to per CPU data */ + refcount_t refcnt; /* Overall active events */ + struct paicrypt_mapptr __percpu *mapptr; +} paicrypt_root; + +/* Free per CPU data when the last event is removed. */ +static void paicrypt_root_free(void) +{ + if (refcount_dec_and_test(&paicrypt_root.refcnt)) { + free_percpu(paicrypt_root.mapptr); + paicrypt_root.mapptr = NULL; + } + debug_sprintf_event(cfm_dbg, 5, "%s root.refcount %d\n", __func__, + refcount_read(&paicrypt_root.refcnt)); +} + +/* + * On initialization of first event also allocate per CPU data dynamically. + * Start with an array of pointers, the array size is the maximum number of + * CPUs possible, which might be larger than the number of CPUs currently + * online. + */ +static int paicrypt_root_alloc(void) +{ + if (!refcount_inc_not_zero(&paicrypt_root.refcnt)) { + /* The memory is already zeroed. */ + paicrypt_root.mapptr = alloc_percpu(struct paicrypt_mapptr); + if (!paicrypt_root.mapptr) + return -ENOMEM; + refcount_set(&paicrypt_root.refcnt, 1); + } + return 0; +} /* Release the PMU if event is the last perf event */ static DEFINE_MUTEX(pai_reserve_mutex); @@ -51,7 +86,9 @@ static DEFINE_MUTEX(pai_reserve_mutex); */ static void paicrypt_event_destroy(struct perf_event *event) { - struct paicrypt_map *cpump = per_cpu_ptr(&paicrypt_map, event->cpu); + struct paicrypt_mapptr *mp = per_cpu_ptr(paicrypt_root.mapptr, + event->cpu); + struct paicrypt_map *cpump = mp->mapptr; cpump->event = NULL; static_branch_dec(&pai_key); @@ -66,11 +103,11 @@ static void paicrypt_event_destroy(struct perf_event *event) __func__, (unsigned long)cpump->page, cpump->save); free_page((unsigned long)cpump->page); - cpump->page = NULL; kvfree(cpump->save); - cpump->save = NULL; - cpump->mode = PAI_MODE_NONE; + kfree(cpump); + mp->mapptr = NULL; } + paicrypt_root_free(); mutex_unlock(&pai_reserve_mutex); } @@ -86,7 +123,8 @@ static u64 paicrypt_getctr(struct paicrypt_map *cpump, int nr, bool kernel) */ static u64 paicrypt_getdata(struct perf_event *event, bool kernel) { - struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map); + struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); + struct paicrypt_map *cpump = mp->mapptr; u64 sum = 0; int i; @@ -132,11 +170,31 @@ static u64 paicrypt_getall(struct perf_event *event) * * Allocate the memory for the event. */ -static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump) +static struct paicrypt_map *paicrypt_busy(struct perf_event *event) { - int rc = 0; + struct perf_event_attr *a = &event->attr; + struct paicrypt_map *cpump = NULL; + struct paicrypt_mapptr *mp; + int rc; mutex_lock(&pai_reserve_mutex); + + /* Allocate root node */ + rc = paicrypt_root_alloc(); + if (rc) + goto unlock; + + /* Allocate node for this event */ + mp = per_cpu_ptr(paicrypt_root.mapptr, event->cpu); + cpump = mp->mapptr; + if (!cpump) { /* Paicrypt_map allocated? */ + cpump = kzalloc(sizeof(*cpump), GFP_KERNEL); + if (!cpump) { + rc = -ENOMEM; + goto free_root; + } + } + if (a->sample_period) { /* Sampling requested */ if (cpump->mode != PAI_MODE_NONE) rc = -EBUSY; /* ... sampling/counting active */ @@ -144,8 +202,15 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump) if (cpump->mode == PAI_MODE_SAMPLING) rc = -EBUSY; /* ... and sampling active */ } + /* + * This error case triggers when there is a conflict: + * Either sampling requested and counting already active, or visa + * versa. Therefore the struct paicrypto_map for this CPU is + * needed or the error could not have occurred. Only adjust root + * node refcount. + */ if (rc) - goto unlock; + goto free_root; /* Allocate memory for counter page and counter extraction. * Only the first counting event has to allocate a page. @@ -158,30 +223,36 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump) rc = -ENOMEM; cpump->page = (unsigned long *)get_zeroed_page(GFP_KERNEL); if (!cpump->page) - goto unlock; + goto free_paicrypt_map; cpump->save = kvmalloc_array(paicrypt_cnt + 1, sizeof(struct pai_userdata), GFP_KERNEL); if (!cpump->save) { free_page((unsigned long)cpump->page); cpump->page = NULL; - goto unlock; + goto free_paicrypt_map; } + + /* Set mode and reference count */ rc = 0; refcount_set(&cpump->refcnt, 1); - -unlock: - /* If rc is non-zero, do not set mode and reference count */ - if (!rc) { - cpump->mode = a->sample_period ? PAI_MODE_SAMPLING - : PAI_MODE_COUNTING; - } + cpump->mode = a->sample_period ? PAI_MODE_SAMPLING : PAI_MODE_COUNTING; + mp->mapptr = cpump; debug_sprintf_event(cfm_dbg, 5, "%s sample_period %#llx users %d" " mode %d refcnt %u page %#lx save %p rc %d\n", __func__, a->sample_period, cpump->active_events, cpump->mode, refcount_read(&cpump->refcnt), (unsigned long)cpump->page, cpump->save, rc); + goto unlock; + +free_paicrypt_map: + kfree(cpump); + mp->mapptr = NULL; +free_root: + paicrypt_root_free(); + +unlock: mutex_unlock(&pai_reserve_mutex); - return rc; + return rc ? ERR_PTR(rc) : cpump; } /* Might be called on different CPU than the one the event is intended for. */ @@ -189,7 +260,6 @@ static int paicrypt_event_init(struct perf_event *event) { struct perf_event_attr *a = &event->attr; struct paicrypt_map *cpump; - int rc; /* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */ if (a->type != PERF_TYPE_RAW && event->pmu->type != a->type) @@ -199,16 +269,15 @@ static int paicrypt_event_init(struct perf_event *event) a->config > PAI_CRYPTO_BASE + paicrypt_cnt) return -EINVAL; /* Allow only CPU wide operation, no process context for now. */ - if (event->hw.target || event->cpu == -1) + if ((event->attach_state & PERF_ATTACH_TASK) || event->cpu == -1) return -ENOENT; /* Allow only CRYPTO_ALL for sampling. */ if (a->sample_period && a->config != PAI_CRYPTO_BASE) return -EINVAL; - cpump = per_cpu_ptr(&paicrypt_map, event->cpu); - rc = paicrypt_busy(a, cpump); - if (rc) - return rc; + cpump = paicrypt_busy(event); + if (IS_ERR(cpump)) + return PTR_ERR(cpump); /* Event initialization sets last_tag to 0. When later on the events * are deleted and re-added, do not reset the event count value to zero. @@ -216,7 +285,6 @@ static int paicrypt_event_init(struct perf_event *event) * are active at the same time. */ event->hw.last_tag = 0; - cpump->event = event; event->destroy = paicrypt_event_destroy; if (a->sample_period) { @@ -253,20 +321,20 @@ static void paicrypt_start(struct perf_event *event, int flags) if (!event->hw.last_tag) { event->hw.last_tag = 1; sum = paicrypt_getall(event); /* Get current value */ - local64_set(&event->count, 0); local64_set(&event->hw.prev_count, sum); } } static int paicrypt_add(struct perf_event *event, int flags) { - struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map); + struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); + struct paicrypt_map *cpump = mp->mapptr; unsigned long ccd; if (++cpump->active_events == 1) { ccd = virt_to_phys(cpump->page) | PAI_CRYPTO_KERNEL_OFFSET; WRITE_ONCE(S390_lowcore.ccd, ccd); - __ctl_set_bit(0, 50); + local_ctl_set_bit(0, CR0_CRYPTOGRAPHY_COUNTER_BIT); } cpump->event = event; if (flags & PERF_EF_START && !event->attr.sample_period) { @@ -287,7 +355,8 @@ static void paicrypt_stop(struct perf_event *event, int flags) static void paicrypt_del(struct perf_event *event, int flags) { - struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map); + struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); + struct paicrypt_map *cpump = mp->mapptr; if (event->attr.sample_period) perf_sched_cb_dec(event->pmu); @@ -295,7 +364,7 @@ static void paicrypt_del(struct perf_event *event, int flags) /* Only counting needs to read counter */ paicrypt_stop(event, PERF_EF_UPDATE); if (--cpump->active_events == 0) { - __ctl_clear_bit(0, 50); + local_ctl_clear_bit(0, CR0_CRYPTOGRAPHY_COUNTER_BIT); WRITE_ONCE(S390_lowcore.ccd, 0); } } @@ -329,7 +398,8 @@ static size_t paicrypt_copy(struct pai_userdata *userdata, static int paicrypt_push_sample(void) { - struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map); + struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); + struct paicrypt_map *cpump = mp->mapptr; struct perf_event *event = cpump->event; struct perf_sample_data data; struct perf_raw_record raw; diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index c57c1a203256..8ba0f1a3a39d 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -17,8 +17,7 @@ #include #include #include - -#include +#include #include #include @@ -249,7 +248,7 @@ static int paiext_event_init(struct perf_event *event) if (rc) return rc; /* Allow only CPU wide operation, no process context for now. */ - if (event->hw.target || event->cpu == -1) + if ((event->attach_state & PERF_ATTACH_TASK) || event->cpu == -1) return -ENOENT; /* Allow only event NNPA_ALL for sampling. */ if (a->sample_period && a->config != PAI_NNPA_BASE) @@ -327,7 +326,6 @@ static void paiext_start(struct perf_event *event, int flags) event->hw.last_tag = 1; sum = paiext_getall(event); /* Get current value */ local64_set(&event->hw.prev_count, sum); - local64_set(&event->count, 0); } static int paiext_add(struct perf_event *event, int flags) @@ -340,7 +338,7 @@ static int paiext_add(struct perf_event *event, int flags) S390_lowcore.aicd = virt_to_phys(cpump->paiext_cb); pcb->acc = virt_to_phys(cpump->area) | 0x1; /* Enable CPU instruction lookup for PAIE1 control block */ - __ctl_set_bit(0, 49); + local_ctl_set_bit(0, CR0_PAI_EXTENSION_BIT); debug_sprintf_event(paiext_dbg, 4, "%s 1508 %llx acc %llx\n", __func__, S390_lowcore.aicd, pcb->acc); } @@ -376,7 +374,7 @@ static void paiext_del(struct perf_event *event, int flags) } if (--cpump->active_events == 0) { /* Disable CPU instruction lookup for PAIE1 control block */ - __ctl_clear_bit(0, 49); + local_ctl_clear_bit(0, CR0_PAI_EXTENSION_BIT); pcb->acc = 0; S390_lowcore.aicd = 0; debug_sprintf_event(paiext_dbg, 4, "%s 1508 %llx acc %llx\n", diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index ea244a73efad..046403471c5d 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -41,13 +41,20 @@ void update_cr_regs(struct task_struct *task) { struct pt_regs *regs = task_pt_regs(task); struct thread_struct *thread = &task->thread; - struct per_regs old, new; union ctlreg0 cr0_old, cr0_new; union ctlreg2 cr2_old, cr2_new; int cr0_changed, cr2_changed; + union { + struct ctlreg regs[3]; + struct { + struct ctlreg control; + struct ctlreg start; + struct ctlreg end; + }; + } old, new; - __ctl_store(cr0_old.val, 0, 0); - __ctl_store(cr2_old.val, 2, 2); + local_ctl_store(0, &cr0_old.reg); + local_ctl_store(2, &cr2_old.reg); cr0_new = cr0_old; cr2_new = cr2_old; /* Take care of the enable/disable of transactional execution. */ @@ -75,38 +82,38 @@ void update_cr_regs(struct task_struct *task) cr0_changed = cr0_new.val != cr0_old.val; cr2_changed = cr2_new.val != cr2_old.val; if (cr0_changed) - __ctl_load(cr0_new.val, 0, 0); + local_ctl_load(0, &cr0_new.reg); if (cr2_changed) - __ctl_load(cr2_new.val, 2, 2); + local_ctl_load(2, &cr2_new.reg); /* Copy user specified PER registers */ - new.control = thread->per_user.control; - new.start = thread->per_user.start; - new.end = thread->per_user.end; + new.control.val = thread->per_user.control; + new.start.val = thread->per_user.start; + new.end.val = thread->per_user.end; /* merge TIF_SINGLE_STEP into user specified PER registers. */ if (test_tsk_thread_flag(task, TIF_SINGLE_STEP) || test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) { if (test_tsk_thread_flag(task, TIF_BLOCK_STEP)) - new.control |= PER_EVENT_BRANCH; + new.control.val |= PER_EVENT_BRANCH; else - new.control |= PER_EVENT_IFETCH; - new.control |= PER_CONTROL_SUSPENSION; - new.control |= PER_EVENT_TRANSACTION_END; + new.control.val |= PER_EVENT_IFETCH; + new.control.val |= PER_CONTROL_SUSPENSION; + new.control.val |= PER_EVENT_TRANSACTION_END; if (test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) - new.control |= PER_EVENT_IFETCH; - new.start = 0; - new.end = -1UL; + new.control.val |= PER_EVENT_IFETCH; + new.start.val = 0; + new.end.val = -1UL; } /* Take care of the PER enablement bit in the PSW. */ - if (!(new.control & PER_EVENT_MASK)) { + if (!(new.control.val & PER_EVENT_MASK)) { regs->psw.mask &= ~PSW_MASK_PER; return; } regs->psw.mask |= PSW_MASK_PER; - __ctl_store(old, 9, 11); + __local_ctl_store(9, 11, old.regs); if (memcmp(&new, &old, sizeof(struct per_regs)) != 0) - __ctl_load(new, 9, 11); + __local_ctl_load(9, 11, new.regs); } void user_enable_single_step(struct task_struct *task) @@ -1107,7 +1114,7 @@ static int s390_gs_cb_set(struct task_struct *target, target->thread.gs_cb = data; *target->thread.gs_cb = gs_cb; if (target == current) { - __ctl_set_bit(2, 4); + local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); restore_gs_cb(target->thread.gs_cb); } preempt_enable(); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index e555b576d3c8..5701356f4f33 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -305,7 +305,7 @@ static void __init setup_zfcpdump(void) return; if (oldmem_data.start) return; - strcat(boot_command_line, " cio_ignore=all,!ipldev,!condev"); + strlcat(boot_command_line, " cio_ignore=all,!ipldev,!condev", COMMAND_LINE_SIZE); console_loglevel = 2; } #else @@ -381,12 +381,6 @@ void stack_free(unsigned long stack) #endif } -void __init __noreturn arch_call_rest_init(void) -{ - smp_reinit_ipl_cpu(); - rest_init(); -} - static unsigned long __init stack_alloc_early(void) { unsigned long stack; @@ -455,7 +449,6 @@ static void __init setup_lowcore(void) lc->restart_fn = (unsigned long) do_restart; lc->restart_data = 0; lc->restart_source = -1U; - __ctl_store(lc->cregs_save_area, 0, 15); lc->spinlock_lockval = arch_spin_lockval(0); lc->spinlock_index = 0; arch_spin_lock_setup(0); @@ -465,6 +458,7 @@ static void __init setup_lowcore(void) lc->kernel_asce = S390_lowcore.kernel_asce; lc->user_asce = S390_lowcore.user_asce; + system_ctlreg_init_save_area(lc); abs_lc = get_abs_lowcore(); abs_lc->restart_stack = lc->restart_stack; abs_lc->restart_fn = lc->restart_fn; @@ -472,7 +466,6 @@ static void __init setup_lowcore(void) abs_lc->restart_source = lc->restart_source; abs_lc->restart_psw = lc->restart_psw; abs_lc->restart_flags = RESTART_FLAG_CTLREGS; - memcpy(abs_lc->cregs_save_area, lc->cregs_save_area, sizeof(abs_lc->cregs_save_area)); abs_lc->program_new_psw = lc->program_new_psw; abs_lc->mcesad = lc->mcesad; put_abs_lowcore(abs_lc); @@ -797,15 +790,15 @@ static void __init setup_cr(void) __ctl_duct[4] = (unsigned long)__ctl_duald; /* Update control registers CR2, CR5 and CR15 */ - __ctl_store(cr2.val, 2, 2); - __ctl_store(cr5.val, 5, 5); - __ctl_store(cr15.val, 15, 15); + local_ctl_store(2, &cr2.reg); + local_ctl_store(5, &cr5.reg); + local_ctl_store(15, &cr15.reg); cr2.ducto = (unsigned long)__ctl_duct >> 6; cr5.pasteo = (unsigned long)__ctl_duct >> 6; cr15.lsea = (unsigned long)__ctl_linkage_stack >> 3; - __ctl_load(cr2.val, 2, 2); - __ctl_load(cr5.val, 5, 5); - __ctl_load(cr15.val, 15, 15); + system_ctl_load(2, &cr2.reg); + system_ctl_load(5, &cr5.reg); + system_ctl_load(15, &cr15.reg); } /* diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 214a1b67f80a..f7fcfff09acf 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -567,54 +568,6 @@ void arch_irq_work_raise(void) } #endif -/* - * parameter area for the set/clear control bit callbacks - */ -struct ec_creg_mask_parms { - unsigned long orval; - unsigned long andval; - int cr; -}; - -/* - * callback for setting/clearing control bits - */ -static void smp_ctl_bit_callback(void *info) -{ - struct ec_creg_mask_parms *pp = info; - unsigned long cregs[16]; - - __ctl_store(cregs, 0, 15); - cregs[pp->cr] = (cregs[pp->cr] & pp->andval) | pp->orval; - __ctl_load(cregs, 0, 15); -} - -static DEFINE_SPINLOCK(ctl_lock); - -void smp_ctl_set_clear_bit(int cr, int bit, bool set) -{ - struct ec_creg_mask_parms parms = { .cr = cr, }; - struct lowcore *abs_lc; - u64 ctlreg; - - if (set) { - parms.orval = 1UL << bit; - parms.andval = -1UL; - } else { - parms.orval = 0; - parms.andval = ~(1UL << bit); - } - spin_lock(&ctl_lock); - abs_lc = get_abs_lowcore(); - ctlreg = abs_lc->cregs_save_area[cr]; - ctlreg = (ctlreg & parms.andval) | parms.orval; - abs_lc->cregs_save_area[cr] = ctlreg; - put_abs_lowcore(abs_lc); - on_each_cpu(smp_ctl_bit_callback, &parms, 1); - spin_unlock(&ctl_lock); -} -EXPORT_SYMBOL(smp_ctl_set_clear_bit); - #ifdef CONFIG_CRASH_DUMP int smp_store_status(int cpu) @@ -935,14 +888,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) * Make sure global control register contents do not change * until new CPU has initialized control registers. */ - spin_lock(&ctl_lock); + system_ctlreg_lock(); pcpu_prepare_secondary(pcpu, cpu); pcpu_attach_task(pcpu, tidle); pcpu_start_fn(pcpu, smp_start_secondary, NULL); /* Wait until cpu puts itself in the online & active maps */ while (!cpu_online(cpu)) cpu_relax(); - spin_unlock(&ctl_lock); + system_ctlreg_unlock(); return 0; } @@ -957,7 +910,7 @@ early_param("possible_cpus", _setup_possible_cpus); int __cpu_disable(void) { - unsigned long cregs[16]; + struct ctlreg cregs[16]; int cpu; /* Handle possible pending IPIs */ @@ -969,11 +922,11 @@ int __cpu_disable(void) /* Disable pseudo page faults on this cpu. */ pfault_fini(); /* Disable interrupt sources via control register. */ - __ctl_store(cregs, 0, 15); - cregs[0] &= ~0x0000ee70UL; /* disable all external interrupts */ - cregs[6] &= ~0xff000000UL; /* disable all I/O interrupts */ - cregs[14] &= ~0x1f000000UL; /* disable most machine checks */ - __ctl_load(cregs, 0, 15); + __local_ctl_store(0, 15, cregs); + cregs[0].val &= ~0x0000ee70UL; /* disable all external interrupts */ + cregs[6].val &= ~0xff000000UL; /* disable all I/O interrupts */ + cregs[14].val &= ~0x1f000000UL; /* disable most machine checks */ + __local_ctl_load(0, 15, cregs); clear_cpu_flag(CIF_NOHZ_DELAY); return 0; } @@ -1013,12 +966,12 @@ void __init smp_fill_possible_mask(void) void __init smp_prepare_cpus(unsigned int max_cpus) { - /* request the 0x1201 emergency signal external interrupt */ if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt)) panic("Couldn't request external interrupt 0x1201"); - /* request the 0x1202 external call external interrupt */ + system_ctl_set_bit(0, 14); if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt)) panic("Couldn't request external interrupt 0x1202"); + system_ctl_set_bit(0, 13); } void __init smp_prepare_boot_cpu(void) @@ -1076,11 +1029,9 @@ static ssize_t cpu_configure_store(struct device *dev, cpus_read_lock(); mutex_lock(&smp_cpu_state_mutex); rc = -EBUSY; - /* disallow configuration changes of online cpus and cpu 0 */ + /* disallow configuration changes of online cpus */ cpu = dev->id; cpu = smp_get_base_cpu(cpu); - if (cpu == 0) - goto out; for (i = 0; i <= smp_cpu_mtid; i++) if (cpu_online(cpu + i)) goto out; @@ -1180,7 +1131,7 @@ static int smp_add_present_cpu(int cpu) return -ENOMEM; per_cpu(cpu_device, cpu) = c; s = &c->dev; - c->hotpluggable = 1; + c->hotpluggable = !!cpu; rc = register_cpu(c, cpu); if (rc) goto out; @@ -1258,60 +1209,3 @@ out: return rc; } subsys_initcall(s390_smp_init); - -static __always_inline void set_new_lowcore(struct lowcore *lc) -{ - union register_pair dst, src; - u32 pfx; - - src.even = (unsigned long) &S390_lowcore; - src.odd = sizeof(S390_lowcore); - dst.even = (unsigned long) lc; - dst.odd = sizeof(*lc); - pfx = __pa(lc); - - asm volatile( - " mvcl %[dst],%[src]\n" - " spx %[pfx]\n" - : [dst] "+&d" (dst.pair), [src] "+&d" (src.pair) - : [pfx] "Q" (pfx) - : "memory", "cc"); -} - -int __init smp_reinit_ipl_cpu(void) -{ - unsigned long async_stack, nodat_stack, mcck_stack; - struct lowcore *lc, *lc_ipl; - unsigned long flags, cr0; - u64 mcesad; - - lc_ipl = lowcore_ptr[0]; - lc = (struct lowcore *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); - nodat_stack = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); - async_stack = stack_alloc(); - mcck_stack = stack_alloc(); - if (!lc || !nodat_stack || !async_stack || !mcck_stack || nmi_alloc_mcesa(&mcesad)) - panic("Couldn't allocate memory"); - - local_irq_save(flags); - local_mcck_disable(); - set_new_lowcore(lc); - S390_lowcore.nodat_stack = nodat_stack + STACK_INIT_OFFSET; - S390_lowcore.async_stack = async_stack + STACK_INIT_OFFSET; - S390_lowcore.mcck_stack = mcck_stack + STACK_INIT_OFFSET; - __ctl_store(cr0, 0, 0); - __ctl_clear_bit(0, 28); /* disable lowcore protection */ - S390_lowcore.mcesad = mcesad; - __ctl_load(cr0, 0, 0); - if (abs_lowcore_map(0, lc, false)) - panic("Couldn't remap absolute lowcore"); - lowcore_ptr[0] = lc; - local_mcck_enable(); - local_irq_restore(flags); - - memblock_free_late(__pa(lc_ipl->mcck_stack - STACK_INIT_OFFSET), THREAD_SIZE); - memblock_free_late(__pa(lc_ipl->async_stack - STACK_INIT_OFFSET), THREAD_SIZE); - memblock_free_late(__pa(lc_ipl->nodat_stack - STACK_INIT_OFFSET), THREAD_SIZE); - memblock_free_late(__pa(lc_ipl), sizeof(*lc_ipl)); - return 0; -} diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index d34d3548c046..14abad953c02 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -173,10 +173,10 @@ void init_cpu_timer(void) clockevents_register_device(cd); /* Enable clock comparator timer interrupt. */ - __ctl_set_bit(0,11); + local_ctl_set_bit(0, CR0_CLOCK_COMPARATOR_SUBMASK_BIT); /* Always allow the timing alert external interrupt. */ - __ctl_set_bit(0, 4); + local_ctl_set_bit(0, CR0_ETR_SUBMASK_BIT); } static void clock_comparator_interrupt(struct ext_code ext_code, diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index ff8349d17b33..5bfcc50c1a68 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -11,7 +11,7 @@ #include #include #include - +#include #include #include "kvm-s390.h" #include "gaccess.h" @@ -466,23 +466,6 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, u8 ar, return 0; } -struct trans_exc_code_bits { - unsigned long addr : 52; /* Translation-exception Address */ - unsigned long fsi : 2; /* Access Exception Fetch/Store Indication */ - unsigned long : 2; - unsigned long b56 : 1; - unsigned long : 3; - unsigned long b60 : 1; - unsigned long b61 : 1; - unsigned long as : 2; /* ASCE Identifier */ -}; - -enum { - FSI_UNKNOWN = 0, /* Unknown whether fetch or store */ - FSI_STORE = 1, /* Exception was due to store operation */ - FSI_FETCH = 2 /* Exception was due to fetch operation */ -}; - enum prot_type { PROT_TYPE_LA = 0, PROT_TYPE_KEYC = 1, @@ -497,11 +480,11 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, enum gacc_mode mode, enum prot_type prot, bool terminate) { struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm; - struct trans_exc_code_bits *tec; + union teid *teid; memset(pgm, 0, sizeof(*pgm)); pgm->code = code; - tec = (struct trans_exc_code_bits *)&pgm->trans_exc_code; + teid = (union teid *)&pgm->trans_exc_code; switch (code) { case PGM_PROTECTION: @@ -511,25 +494,25 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, WARN_ON_ONCE(1); break; case PROT_TYPE_IEP: - tec->b61 = 1; + teid->b61 = 1; fallthrough; case PROT_TYPE_LA: - tec->b56 = 1; + teid->b56 = 1; break; case PROT_TYPE_KEYC: - tec->b60 = 1; + teid->b60 = 1; break; case PROT_TYPE_ALC: - tec->b60 = 1; + teid->b60 = 1; fallthrough; case PROT_TYPE_DAT: - tec->b61 = 1; + teid->b61 = 1; break; } if (terminate) { - tec->b56 = 0; - tec->b60 = 0; - tec->b61 = 0; + teid->b56 = 0; + teid->b60 = 0; + teid->b61 = 0; } fallthrough; case PGM_ASCE_TYPE: @@ -543,9 +526,9 @@ static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, * exc_access_id has to be set to 0 for some instructions. Both * cases have to be handled by the caller. */ - tec->addr = gva >> PAGE_SHIFT; - tec->fsi = mode == GACC_STORE ? FSI_STORE : FSI_FETCH; - tec->as = psw_bits(vcpu->arch.sie_block->gpsw).as; + teid->addr = gva >> PAGE_SHIFT; + teid->fsi = mode == GACC_STORE ? TEID_FSI_STORE : TEID_FSI_FETCH; + teid->as = psw_bits(vcpu->arch.sie_block->gpsw).as; fallthrough; case PGM_ALEN_TRANSLATION: case PGM_ALE_SEQUENCE: diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 11676b81e6bf..7aa0e668488f 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -4927,7 +4927,7 @@ static void sync_regs_fmt2(struct kvm_vcpu *vcpu) } if (MACHINE_HAS_GS) { preempt_disable(); - __ctl_set_bit(2, 4); + local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); if (current->thread.gs_cb) { vcpu->arch.host_gscb = current->thread.gs_cb; save_gs_cb(vcpu->arch.host_gscb); @@ -5004,13 +5004,13 @@ static void store_regs_fmt2(struct kvm_vcpu *vcpu) kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val; if (MACHINE_HAS_GS) { preempt_disable(); - __ctl_set_bit(2, 4); + local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); if (vcpu->arch.gs_enabled) save_gs_cb(current->thread.gs_cb); current->thread.gs_cb = vcpu->arch.host_gscb; restore_gs_cb(vcpu->arch.host_gscb); if (!vcpu->arch.host_gscb) - __ctl_clear_bit(2, 4); + local_ctl_clear_bit(2, CR2_GUARDED_STORAGE_BIT); vcpu->arch.host_gscb = NULL; preempt_enable(); } diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index dc4cfa8795c0..621a17fd1a1b 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -57,7 +57,7 @@ static int handle_gs(struct kvm_vcpu *vcpu) if (test_kvm_facility(vcpu->kvm, 133)) { VCPU_EVENT(vcpu, 3, "%s", "ENABLE: GS (lazy)"); preempt_disable(); - __ctl_set_bit(2, 4); + local_ctl_set_bit(2, CR2_GUARDED_STORAGE_BIT); current->thread.gs_cb = (struct gs_cb *)&vcpu->run->s.regs.gscb; restore_gs_cb(current->thread.gs_cb); preempt_enable(); diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c index e4a13d7cab6e..61d8dcd95bbc 100644 --- a/arch/s390/lib/uaccess.c +++ b/arch/s390/lib/uaccess.c @@ -12,21 +12,22 @@ #include #include #include +#include #ifdef CONFIG_DEBUG_ENTRY void debug_user_asce(int exit) { - unsigned long cr1, cr7; + struct ctlreg cr1, cr7; - __ctl_store(cr1, 1, 1); - __ctl_store(cr7, 7, 7); - if (cr1 == S390_lowcore.kernel_asce && cr7 == S390_lowcore.user_asce) + local_ctl_store(1, &cr1); + local_ctl_store(7, &cr7); + if (cr1.val == S390_lowcore.kernel_asce.val && cr7.val == S390_lowcore.user_asce.val) return; panic("incorrect ASCE on kernel %s\n" "cr1: %016lx cr7: %016lx\n" - "kernel: %016llx user: %016llx\n", - exit ? "exit" : "entry", cr1, cr7, - S390_lowcore.kernel_asce, S390_lowcore.user_asce); + "kernel: %016lx user: %016lx\n", + exit ? "exit" : "entry", cr1.val, cr7.val, + S390_lowcore.kernel_asce.val, S390_lowcore.user_asce.val); } #endif /*CONFIG_DEBUG_ENTRY */ diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index b51666967aa1..d37a8f607b71 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -287,7 +287,7 @@ static int pt_dump_init(void) * kernel ASCE. We need this to keep the page table walker functions * from accessing non-existent entries. */ - max_addr = (S390_lowcore.kernel_asce & _REGION_ENTRY_TYPE_MASK) >> 2; + max_addr = (S390_lowcore.kernel_asce.val & _REGION_ENTRY_TYPE_MASK) >> 2; max_addr = 1UL << (max_addr * 11 + 31); address_markers[IDENTITY_AFTER_END_NR].start_address = ident_map_size; address_markers[AMODE31_START_NR].start_address = (unsigned long)__samode31; diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c index fe87291df95d..0a0738a473af 100644 --- a/arch/s390/mm/extable.c +++ b/arch/s390/mm/extable.c @@ -61,6 +61,22 @@ static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex, return true; } +static bool ex_handler_zeropad(const struct exception_table_entry *ex, struct pt_regs *regs) +{ + unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data); + unsigned int reg_data = FIELD_GET(EX_DATA_REG_ERR, ex->data); + unsigned long data, addr, offset; + + addr = regs->gprs[reg_addr]; + offset = addr & (sizeof(unsigned long) - 1); + addr &= ~(sizeof(unsigned long) - 1); + data = *(unsigned long *)addr; + data <<= BITS_PER_BYTE * offset; + regs->gprs[reg_data] = data; + regs->psw.addr = extable_fixup(ex); + return true; +} + bool fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *ex; @@ -81,6 +97,8 @@ bool fixup_exception(struct pt_regs *regs) return ex_handler_ua_load_reg(ex, false, regs); case EX_TYPE_UA_LOAD_REGPAIR: return ex_handler_ua_load_reg(ex, true, regs); + case EX_TYPE_ZEROPAD: + return ex_handler_zeropad(ex, regs); } panic("invalid exception table entry"); } diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index b678295931c3..249aefcf7c4e 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -3,17 +3,19 @@ * S390 version * Copyright IBM Corp. 1999 * Author(s): Hartmut Penner (hp@de.ibm.com) - * Ulrich Weigand (uweigand@de.ibm.com) + * Ulrich Weigand (uweigand@de.ibm.com) * * Derived from "arch/i386/mm/fault.c" * Copyright (C) 1995 Linus Torvalds */ #include +#include #include #include #include #include +#include #include #include #include @@ -34,38 +36,27 @@ #include #include #include +#include +#include #include #include #include -#include #include #include #include "../kernel/entry.h" -#define __FAIL_ADDR_MASK -4096L - -/* - * Allocate private vm_fault_reason from top. Please make sure it won't - * collide with vm_fault_reason. - */ -#define VM_FAULT_BADCONTEXT ((__force vm_fault_t)0x80000000) -#define VM_FAULT_BADMAP ((__force vm_fault_t)0x40000000) -#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x20000000) -#define VM_FAULT_SIGNAL ((__force vm_fault_t)0x10000000) -#define VM_FAULT_PFAULT ((__force vm_fault_t)0x8000000) - enum fault_type { KERNEL_FAULT, USER_FAULT, GMAP_FAULT, }; -static unsigned long store_indication __read_mostly; +static DEFINE_STATIC_KEY_FALSE(have_store_indication); static int __init fault_init(void) { if (test_facility(75)) - store_indication = 0xc00; + static_branch_enable(&have_store_indication); return 0; } early_initcall(fault_init); @@ -75,11 +66,9 @@ early_initcall(fault_init); */ static enum fault_type get_fault_type(struct pt_regs *regs) { - unsigned long trans_exc_code; + union teid teid = { .val = regs->int_parm_long }; - trans_exc_code = regs->int_parm_long & 3; - if (likely(trans_exc_code == 0)) { - /* primary space exception */ + if (likely(teid.as == PSW_BITS_AS_PRIMARY)) { if (user_mode(regs)) return USER_FAULT; if (!IS_ENABLED(CONFIG_PGSTE)) @@ -88,83 +77,77 @@ static enum fault_type get_fault_type(struct pt_regs *regs) return GMAP_FAULT; return KERNEL_FAULT; } - if (trans_exc_code == 2) + if (teid.as == PSW_BITS_AS_SECONDARY) return USER_FAULT; - if (trans_exc_code == 1) { - /* access register mode, not used in the kernel */ + /* Access register mode, not used in the kernel */ + if (teid.as == PSW_BITS_AS_ACCREG) return USER_FAULT; - } - /* home space exception -> access via kernel ASCE */ + /* Home space -> access via kernel ASCE */ return KERNEL_FAULT; } static unsigned long get_fault_address(struct pt_regs *regs) { - unsigned long trans_exc_code = regs->int_parm_long; + union teid teid = { .val = regs->int_parm_long }; - return trans_exc_code & __FAIL_ADDR_MASK; + return teid.addr * PAGE_SIZE; } -static bool fault_is_write(struct pt_regs *regs) +static __always_inline bool fault_is_write(struct pt_regs *regs) { - unsigned long trans_exc_code = regs->int_parm_long; + union teid teid = { .val = regs->int_parm_long }; - return (trans_exc_code & store_indication) == 0x400; -} - -static int bad_address(void *p) -{ - unsigned long dummy; - - return get_kernel_nofault(dummy, (unsigned long *)p); + if (static_branch_likely(&have_store_indication)) + return teid.fsi == TEID_FSI_STORE; + return false; } static void dump_pagetable(unsigned long asce, unsigned long address) { - unsigned long *table = __va(asce & _ASCE_ORIGIN); + unsigned long entry, *table = __va(asce & _ASCE_ORIGIN); pr_alert("AS:%016lx ", asce); switch (asce & _ASCE_TYPE_MASK) { case _ASCE_TYPE_REGION1: table += (address & _REGION1_INDEX) >> _REGION1_SHIFT; - if (bad_address(table)) + if (get_kernel_nofault(entry, table)) goto bad; - pr_cont("R1:%016lx ", *table); - if (*table & _REGION_ENTRY_INVALID) + pr_cont("R1:%016lx ", entry); + if (entry & _REGION_ENTRY_INVALID) goto out; - table = __va(*table & _REGION_ENTRY_ORIGIN); + table = __va(entry & _REGION_ENTRY_ORIGIN); fallthrough; case _ASCE_TYPE_REGION2: table += (address & _REGION2_INDEX) >> _REGION2_SHIFT; - if (bad_address(table)) + if (get_kernel_nofault(entry, table)) goto bad; - pr_cont("R2:%016lx ", *table); - if (*table & _REGION_ENTRY_INVALID) + pr_cont("R2:%016lx ", entry); + if (entry & _REGION_ENTRY_INVALID) goto out; - table = __va(*table & _REGION_ENTRY_ORIGIN); + table = __va(entry & _REGION_ENTRY_ORIGIN); fallthrough; case _ASCE_TYPE_REGION3: table += (address & _REGION3_INDEX) >> _REGION3_SHIFT; - if (bad_address(table)) + if (get_kernel_nofault(entry, table)) goto bad; - pr_cont("R3:%016lx ", *table); - if (*table & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE)) + pr_cont("R3:%016lx ", entry); + if (entry & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE)) goto out; - table = __va(*table & _REGION_ENTRY_ORIGIN); + table = __va(entry & _REGION_ENTRY_ORIGIN); fallthrough; case _ASCE_TYPE_SEGMENT: table += (address & _SEGMENT_INDEX) >> _SEGMENT_SHIFT; - if (bad_address(table)) + if (get_kernel_nofault(entry, table)) goto bad; - pr_cont("S:%016lx ", *table); - if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE)) + pr_cont("S:%016lx ", entry); + if (entry & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE)) goto out; - table = __va(*table & _SEGMENT_ENTRY_ORIGIN); + table = __va(entry & _SEGMENT_ENTRY_ORIGIN); } table += (address & _PAGE_INDEX) >> _PAGE_SHIFT; - if (bad_address(table)) + if (get_kernel_nofault(entry, table)) goto bad; - pr_cont("P:%016lx ", *table); + pr_cont("P:%016lx ", entry); out: pr_cont("\n"); return; @@ -174,173 +157,113 @@ bad: static void dump_fault_info(struct pt_regs *regs) { + union teid teid = { .val = regs->int_parm_long }; unsigned long asce; pr_alert("Failing address: %016lx TEID: %016lx\n", - regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long); + get_fault_address(regs), teid.val); pr_alert("Fault in "); - switch (regs->int_parm_long & 3) { - case 3: + switch (teid.as) { + case PSW_BITS_AS_HOME: pr_cont("home space "); break; - case 2: + case PSW_BITS_AS_SECONDARY: pr_cont("secondary space "); break; - case 1: + case PSW_BITS_AS_ACCREG: pr_cont("access register "); break; - case 0: + case PSW_BITS_AS_PRIMARY: pr_cont("primary space "); break; } pr_cont("mode while using "); switch (get_fault_type(regs)) { case USER_FAULT: - asce = S390_lowcore.user_asce; + asce = S390_lowcore.user_asce.val; pr_cont("user "); break; case GMAP_FAULT: - asce = ((struct gmap *) S390_lowcore.gmap)->asce; + asce = ((struct gmap *)S390_lowcore.gmap)->asce; pr_cont("gmap "); break; case KERNEL_FAULT: - asce = S390_lowcore.kernel_asce; + asce = S390_lowcore.kernel_asce.val; pr_cont("kernel "); break; default: unreachable(); } pr_cont("ASCE.\n"); - dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK); + dump_pagetable(asce, get_fault_address(regs)); } int show_unhandled_signals = 1; void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault) { + static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); + if ((task_pid_nr(current) > 1) && !show_unhandled_signals) return; if (!unhandled_signal(current, signr)) return; - if (!printk_ratelimit()) + if (!__ratelimit(&rs)) return; - printk(KERN_ALERT "User process fault: interruption code %04x ilc:%d ", - regs->int_code & 0xffff, regs->int_code >> 17); + pr_alert("User process fault: interruption code %04x ilc:%d ", + regs->int_code & 0xffff, regs->int_code >> 17); print_vma_addr(KERN_CONT "in ", regs->psw.addr); - printk(KERN_CONT "\n"); + pr_cont("\n"); if (is_mm_fault) dump_fault_info(regs); show_regs(regs); } -/* - * Send SIGSEGV to task. This is an external routine - * to keep the stack usage of do_page_fault small. - */ -static noinline void do_sigsegv(struct pt_regs *regs, int si_code) +static void do_sigsegv(struct pt_regs *regs, int si_code) { report_user_fault(regs, SIGSEGV, 1); - force_sig_fault(SIGSEGV, si_code, - (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK)); + force_sig_fault(SIGSEGV, si_code, (void __user *)get_fault_address(regs)); } -static noinline void do_no_context(struct pt_regs *regs, vm_fault_t fault) +static void handle_fault_error_nolock(struct pt_regs *regs, int si_code) { enum fault_type fault_type; unsigned long address; bool is_write; + if (user_mode(regs)) { + if (WARN_ON_ONCE(!si_code)) + si_code = SEGV_MAPERR; + return do_sigsegv(regs, si_code); + } if (fixup_exception(regs)) return; fault_type = get_fault_type(regs); - if ((fault_type == KERNEL_FAULT) && (fault == VM_FAULT_BADCONTEXT)) { + if (fault_type == KERNEL_FAULT) { address = get_fault_address(regs); is_write = fault_is_write(regs); if (kfence_handle_page_fault(address, is_write, regs)) return; } - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ if (fault_type == KERNEL_FAULT) - printk(KERN_ALERT "Unable to handle kernel pointer dereference" - " in virtual kernel address space\n"); + pr_alert("Unable to handle kernel pointer dereference in virtual kernel address space\n"); else - printk(KERN_ALERT "Unable to handle kernel paging request" - " in virtual user address space\n"); + pr_alert("Unable to handle kernel paging request in virtual user address space\n"); dump_fault_info(regs); die(regs, "Oops"); } -static noinline void do_low_address(struct pt_regs *regs) +static void handle_fault_error(struct pt_regs *regs, int si_code) { - /* Low-address protection hit in kernel mode means - NULL pointer write access in kernel mode. */ - if (regs->psw.mask & PSW_MASK_PSTATE) { - /* Low-address protection hit in user mode 'cannot happen'. */ - die (regs, "Low-address protection"); - } + struct mm_struct *mm = current->mm; - do_no_context(regs, VM_FAULT_BADACCESS); + mmap_read_unlock(mm); + handle_fault_error_nolock(regs, si_code); } -static noinline void do_sigbus(struct pt_regs *regs) +static void do_sigbus(struct pt_regs *regs) { - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - force_sig_fault(SIGBUS, BUS_ADRERR, - (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK)); -} - -static noinline void do_fault_error(struct pt_regs *regs, vm_fault_t fault) -{ - int si_code; - - switch (fault) { - case VM_FAULT_BADACCESS: - case VM_FAULT_BADMAP: - /* Bad memory access. Check if it is kernel or user space. */ - if (user_mode(regs)) { - /* User mode accesses just cause a SIGSEGV */ - si_code = (fault == VM_FAULT_BADMAP) ? - SEGV_MAPERR : SEGV_ACCERR; - do_sigsegv(regs, si_code); - break; - } - fallthrough; - case VM_FAULT_BADCONTEXT: - case VM_FAULT_PFAULT: - do_no_context(regs, fault); - break; - case VM_FAULT_SIGNAL: - if (!user_mode(regs)) - do_no_context(regs, fault); - break; - default: /* fault & VM_FAULT_ERROR */ - if (fault & VM_FAULT_OOM) { - if (!user_mode(regs)) - do_no_context(regs, fault); - else - pagefault_out_of_memory(); - } else if (fault & VM_FAULT_SIGSEGV) { - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - do_no_context(regs, fault); - else - do_sigsegv(regs, SEGV_MAPERR); - } else if (fault & VM_FAULT_SIGBUS) { - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - do_no_context(regs, fault); - else - do_sigbus(regs); - } else - BUG(); - break; - } + force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)get_fault_address(regs)); } /* @@ -349,20 +272,20 @@ static noinline void do_fault_error(struct pt_regs *regs, vm_fault_t fault) * routines. * * interruption code (int_code): - * 04 Protection -> Write-Protection (suppression) - * 10 Segment translation -> Not present (nullification) - * 11 Page translation -> Not present (nullification) - * 3b Region third trans. -> Not present (nullification) + * 04 Protection -> Write-Protection (suppression) + * 10 Segment translation -> Not present (nullification) + * 11 Page translation -> Not present (nullification) + * 3b Region third trans. -> Not present (nullification) */ -static inline vm_fault_t do_exception(struct pt_regs *regs, int access) +static void do_exception(struct pt_regs *regs, int access) { - struct gmap *gmap; - struct task_struct *tsk; - struct mm_struct *mm; struct vm_area_struct *vma; - enum fault_type type; + struct task_struct *tsk; unsigned long address; + struct mm_struct *mm; + enum fault_type type; unsigned int flags; + struct gmap *gmap; vm_fault_t fault; bool is_write; @@ -372,31 +295,21 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access) * been nullified. Don't signal single step via SIGTRAP. */ clear_thread_flag(TIF_PER_TRAP); - if (kprobe_page_fault(regs, 14)) - return 0; - + return; mm = tsk->mm; address = get_fault_address(regs); is_write = fault_is_write(regs); - - /* - * Verify that the fault happened in user space, that - * we are not in an interrupt and that there is a - * user context. - */ - fault = VM_FAULT_BADCONTEXT; type = get_fault_type(regs); switch (type) { case KERNEL_FAULT: - goto out; + return handle_fault_error_nolock(regs, 0); case USER_FAULT: case GMAP_FAULT: if (faulthandler_disabled() || !mm) - goto out; + return handle_fault_error_nolock(regs, 0); break; } - perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); flags = FAULT_FLAG_DEFAULT; if (user_mode(regs)) @@ -419,125 +332,117 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access) vma_end_read(vma); if (!(fault & VM_FAULT_RETRY)) { count_vm_vma_lock_event(VMA_LOCK_SUCCESS); - if (likely(!(fault & VM_FAULT_ERROR))) - fault = 0; - goto out; + if (unlikely(fault & VM_FAULT_ERROR)) + goto error; + return; } count_vm_vma_lock_event(VMA_LOCK_RETRY); /* Quick path to respond to signals */ if (fault_signal_pending(fault, regs)) { - fault = VM_FAULT_SIGNAL; - goto out; + if (!user_mode(regs)) + handle_fault_error_nolock(regs, 0); + return; } lock_mmap: mmap_read_lock(mm); - gmap = NULL; if (IS_ENABLED(CONFIG_PGSTE) && type == GMAP_FAULT) { - gmap = (struct gmap *) S390_lowcore.gmap; + gmap = (struct gmap *)S390_lowcore.gmap; current->thread.gmap_addr = address; current->thread.gmap_write_flag = !!(flags & FAULT_FLAG_WRITE); current->thread.gmap_int_code = regs->int_code & 0xffff; address = __gmap_translate(gmap, address); - if (address == -EFAULT) { - fault = VM_FAULT_BADMAP; - goto out_up; - } + if (address == -EFAULT) + return handle_fault_error(regs, SEGV_MAPERR); if (gmap->pfault_enabled) flags |= FAULT_FLAG_RETRY_NOWAIT; } - retry: - fault = VM_FAULT_BADMAP; vma = find_vma(mm, address); if (!vma) - goto out_up; - + return handle_fault_error(regs, SEGV_MAPERR); if (unlikely(vma->vm_start > address)) { if (!(vma->vm_flags & VM_GROWSDOWN)) - goto out_up; + return handle_fault_error(regs, SEGV_MAPERR); vma = expand_stack(mm, address); if (!vma) - goto out; + return handle_fault_error_nolock(regs, SEGV_MAPERR); } - - /* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ - fault = VM_FAULT_BADACCESS; if (unlikely(!(vma->vm_flags & access))) - goto out_up; - - /* - * If for any reason at all we couldn't handle the fault, - * make sure we exit gracefully rather than endlessly redo - * the fault. - */ + return handle_fault_error(regs, SEGV_ACCERR); fault = handle_mm_fault(vma, address, flags, regs); if (fault_signal_pending(fault, regs)) { - fault = VM_FAULT_SIGNAL; if (flags & FAULT_FLAG_RETRY_NOWAIT) - goto out_up; - goto out; + mmap_read_unlock(mm); + if (!user_mode(regs)) + handle_fault_error_nolock(regs, 0); + return; } - /* The fault is fully completed (including releasing mmap lock) */ if (fault & VM_FAULT_COMPLETED) { if (gmap) { mmap_read_lock(mm); - goto out_gmap; + goto gmap; } - fault = 0; - goto out; + return; + } + if (unlikely(fault & VM_FAULT_ERROR)) { + mmap_read_unlock(mm); + goto error; } - - if (unlikely(fault & VM_FAULT_ERROR)) - goto out_up; - if (fault & VM_FAULT_RETRY) { - if (IS_ENABLED(CONFIG_PGSTE) && gmap && - (flags & FAULT_FLAG_RETRY_NOWAIT)) { + if (IS_ENABLED(CONFIG_PGSTE) && gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) { /* - * FAULT_FLAG_RETRY_NOWAIT has been set, mmap_lock has - * not been released + * FAULT_FLAG_RETRY_NOWAIT has been set, + * mmap_lock has not been released */ current->thread.gmap_pfault = 1; - fault = VM_FAULT_PFAULT; - goto out_up; + return handle_fault_error(regs, 0); } flags &= ~FAULT_FLAG_RETRY_NOWAIT; flags |= FAULT_FLAG_TRIED; mmap_read_lock(mm); goto retry; } -out_gmap: +gmap: if (IS_ENABLED(CONFIG_PGSTE) && gmap) { address = __gmap_link(gmap, current->thread.gmap_addr, address); - if (address == -EFAULT) { - fault = VM_FAULT_BADMAP; - goto out_up; - } + if (address == -EFAULT) + return handle_fault_error(regs, SEGV_MAPERR); if (address == -ENOMEM) { fault = VM_FAULT_OOM; - goto out_up; + mmap_read_unlock(mm); + goto error; } } - fault = 0; -out_up: mmap_read_unlock(mm); -out: - return fault; + return; +error: + if (fault & VM_FAULT_OOM) { + if (!user_mode(regs)) + handle_fault_error_nolock(regs, 0); + else + pagefault_out_of_memory(); + } else if (fault & VM_FAULT_SIGSEGV) { + if (!user_mode(regs)) + handle_fault_error_nolock(regs, 0); + else + do_sigsegv(regs, SEGV_MAPERR); + } else if (fault & VM_FAULT_SIGBUS) { + if (!user_mode(regs)) + handle_fault_error_nolock(regs, 0); + else + do_sigbus(regs); + } else { + BUG(); + } } void do_protection_exception(struct pt_regs *regs) { - unsigned long trans_exc_code; - int access; - vm_fault_t fault; + union teid teid = { .val = regs->int_parm_long }; - trans_exc_code = regs->int_parm_long; /* * Protection exceptions are suppressing, decrement psw address. * The exception to this rule are aborted transactions, for these @@ -550,33 +455,28 @@ void do_protection_exception(struct pt_regs *regs) * as a special case because the translation exception code * field is not guaranteed to contain valid data in this case. */ - if (unlikely(!(trans_exc_code & 4))) { - do_low_address(regs); - return; + if (unlikely(!teid.b61)) { + if (user_mode(regs)) { + /* Low-address protection in user mode: cannot happen */ + die(regs, "Low-address protection"); + } + /* + * Low-address protection in kernel mode means + * NULL pointer write access in kernel mode. + */ + return handle_fault_error_nolock(regs, 0); } - if (unlikely(MACHINE_HAS_NX && (trans_exc_code & 0x80))) { - regs->int_parm_long = (trans_exc_code & ~PAGE_MASK) | - (regs->psw.addr & PAGE_MASK); - access = VM_EXEC; - fault = VM_FAULT_BADACCESS; - } else { - access = VM_WRITE; - fault = do_exception(regs, access); + if (unlikely(MACHINE_HAS_NX && teid.b56)) { + regs->int_parm_long = (teid.addr * PAGE_SIZE) | (regs->psw.addr & PAGE_MASK); + return handle_fault_error_nolock(regs, SEGV_ACCERR); } - if (unlikely(fault)) - do_fault_error(regs, fault); + do_exception(regs, VM_WRITE); } NOKPROBE_SYMBOL(do_protection_exception); void do_dat_exception(struct pt_regs *regs) { - int access; - vm_fault_t fault; - - access = VM_ACCESS_FLAGS; - fault = do_exception(regs, access); - if (unlikely(fault)) - do_fault_error(regs, fault); + do_exception(regs, VM_ACCESS_FLAGS); } NOKPROBE_SYMBOL(do_dat_exception); @@ -584,7 +484,8 @@ NOKPROBE_SYMBOL(do_dat_exception); void do_secure_storage_access(struct pt_regs *regs) { - unsigned long addr = regs->int_parm_long & __FAIL_ADDR_MASK; + union teid teid = { .val = regs->int_parm_long }; + unsigned long addr = get_fault_address(regs); struct vm_area_struct *vma; struct mm_struct *mm; struct page *page; @@ -592,14 +493,12 @@ void do_secure_storage_access(struct pt_regs *regs) int rc; /* - * bit 61 tells us if the address is valid, if it's not we - * have a major problem and should stop the kernel or send a - * SIGSEGV to the process. Unfortunately bit 61 is not - * reliable without the misc UV feature so we need to check - * for that as well. + * Bit 61 indicates if the address is valid, if it is not the + * kernel should be stopped or SIGSEGV should be sent to the + * process. Bit 61 is not reliable without the misc UV feature, + * therefore this needs to be checked too. */ - if (uv_has_feature(BIT_UV_FEAT_MISC) && - !test_bit_inv(61, ®s->int_parm_long)) { + if (uv_has_feature(BIT_UV_FEAT_MISC) && !teid.b61) { /* * When this happens, userspace did something that it * was not supposed to do, e.g. branching into secure @@ -609,14 +508,12 @@ void do_secure_storage_access(struct pt_regs *regs) send_sig(SIGSEGV, current, 0); return; } - /* - * The kernel should never run into this case and we - * have no way out of this situation. + * The kernel should never run into this case and + * there is no way out of this situation. */ panic("Unexpected PGM 0x3d with TEID bit 61=0"); } - switch (get_fault_type(regs)) { case GMAP_FAULT: mm = current->mm; @@ -624,20 +521,15 @@ void do_secure_storage_access(struct pt_regs *regs) mmap_read_lock(mm); addr = __gmap_translate(gmap, addr); mmap_read_unlock(mm); - if (IS_ERR_VALUE(addr)) { - do_fault_error(regs, VM_FAULT_BADMAP); - break; - } + if (IS_ERR_VALUE(addr)) + return handle_fault_error_nolock(regs, SEGV_MAPERR); fallthrough; case USER_FAULT: mm = current->mm; mmap_read_lock(mm); vma = find_vma(mm, addr); - if (!vma) { - mmap_read_unlock(mm); - do_fault_error(regs, VM_FAULT_BADMAP); - break; - } + if (!vma) + return handle_fault_error(regs, SEGV_MAPERR); page = follow_page(vma, addr, FOLL_WRITE | FOLL_GET); if (IS_ERR_OR_NULL(page)) { mmap_read_unlock(mm); @@ -658,23 +550,18 @@ void do_secure_storage_access(struct pt_regs *regs) BUG(); break; default: - do_fault_error(regs, VM_FAULT_BADMAP); - WARN_ON_ONCE(1); + unreachable(); } } NOKPROBE_SYMBOL(do_secure_storage_access); void do_non_secure_storage_access(struct pt_regs *regs) { - unsigned long gaddr = regs->int_parm_long & __FAIL_ADDR_MASK; struct gmap *gmap = (struct gmap *)S390_lowcore.gmap; + unsigned long gaddr = get_fault_address(regs); - if (get_fault_type(regs) != GMAP_FAULT) { - do_fault_error(regs, VM_FAULT_BADMAP); - WARN_ON_ONCE(1); - return; - } - + if (WARN_ON_ONCE(get_fault_type(regs) != GMAP_FAULT)) + return handle_fault_error_nolock(regs, SEGV_MAPERR); if (gmap_convert_to_secure(gmap, gaddr) == -EINVAL) send_sig(SIGSEGV, current, 0); } @@ -682,8 +569,8 @@ NOKPROBE_SYMBOL(do_non_secure_storage_access); void do_secure_storage_violation(struct pt_regs *regs) { - unsigned long gaddr = regs->int_parm_long & __FAIL_ADDR_MASK; struct gmap *gmap = (struct gmap *)S390_lowcore.gmap; + unsigned long gaddr = get_fault_address(regs); /* * If the VM has been rebooted, its address space might still contain @@ -699,9 +586,8 @@ void do_secure_storage_violation(struct pt_regs *regs) * This exception is only triggered when a guest 2 is running * and can therefore never occur in kernel context. */ - printk_ratelimited(KERN_WARNING - "Secure storage violation in task: %s, pid %d\n", - current->comm, current->pid); + pr_warn_ratelimited("Secure storage violation in task: %s, pid %d\n", + current->comm, current->pid); send_sig(SIGSEGV, current, 0); } diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 906a7bfc2a78..20786f6883b2 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c @@ -21,10 +21,22 @@ #include #include +#include #include #define GMAP_SHADOW_FAKE_TABLE 1ULL +static struct page *gmap_alloc_crst(void) +{ + struct page *page; + + page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + if (!page) + return NULL; + arch_set_page_dat(page, CRST_ALLOC_ORDER); + return page; +} + /** * gmap_alloc - allocate and initialize a guest address space * @limit: maximum address of the gmap address space @@ -67,7 +79,7 @@ static struct gmap *gmap_alloc(unsigned long limit) spin_lock_init(&gmap->guest_table_lock); spin_lock_init(&gmap->shadow_lock); refcount_set(&gmap->ref_count, 1); - page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + page = gmap_alloc_crst(); if (!page) goto out_free; page->index = 0; @@ -308,7 +320,7 @@ static int gmap_alloc_table(struct gmap *gmap, unsigned long *table, unsigned long *new; /* since we dont free the gmap table until gmap_free we can unlock */ - page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + page = gmap_alloc_crst(); if (!page) return -ENOMEM; new = page_to_virt(page); @@ -1759,7 +1771,7 @@ int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t, BUG_ON(!gmap_is_shadow(sg)); /* Allocate a shadow region second table */ - page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + page = gmap_alloc_crst(); if (!page) return -ENOMEM; page->index = r2t & _REGION_ENTRY_ORIGIN; @@ -1843,7 +1855,7 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t, BUG_ON(!gmap_is_shadow(sg)); /* Allocate a shadow region second table */ - page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + page = gmap_alloc_crst(); if (!page) return -ENOMEM; page->index = r3t & _REGION_ENTRY_ORIGIN; @@ -1927,7 +1939,7 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt, BUG_ON(!gmap_is_shadow(sg) || (sgt & _REGION3_ENTRY_LARGE)); /* Allocate a shadow segment table */ - page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + page = gmap_alloc_crst(); if (!page) return -ENOMEM; page->index = sgt & _REGION_ENTRY_ORIGIN; @@ -2855,7 +2867,7 @@ int s390_replace_asce(struct gmap *gmap) if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT) return -EINVAL; - page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER); + page = gmap_alloc_crst(); if (!page) return -ENOMEM; page->index = 0; diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 8b94d2212d33..7eca10c32caa 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -54,7 +54,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __section(".bss..swapper_pg_dir"); pgd_t invalid_pg_dir[PTRS_PER_PGD] __section(".bss..invalid_pg_dir"); -unsigned long __bootdata_preserved(s390_invalid_asce); +struct ctlreg __bootdata_preserved(s390_invalid_asce); unsigned long empty_zero_page, zero_page_mask; EXPORT_SYMBOL(empty_zero_page); diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index c805b3e2592b..632c3a55feed 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -15,10 +15,10 @@ #include #include #include -#include #include #include #include +#include unsigned long __bootdata_preserved(__memcpy_real_area); pte_t *__bootdata_preserved(memcpy_real_ptep); diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c index 1e2ea706aa22..a31acb2c4ef2 100644 --- a/arch/s390/mm/page-states.c +++ b/arch/s390/mm/page-states.c @@ -121,7 +121,7 @@ static void mark_kernel_pud(p4d_t *p4d, unsigned long addr, unsigned long end) continue; if (!pud_folded(*pud)) { page = phys_to_page(pud_val(*pud)); - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) set_bit(PG_arch_1, &page[i].flags); } mark_kernel_pmd(pud, addr, next); @@ -142,7 +142,7 @@ static void mark_kernel_p4d(pgd_t *pgd, unsigned long addr, unsigned long end) continue; if (!p4d_folded(*p4d)) { page = phys_to_page(p4d_val(*p4d)); - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) set_bit(PG_arch_1, &page[i].flags); } mark_kernel_pud(p4d, addr, next); @@ -151,24 +151,31 @@ static void mark_kernel_p4d(pgd_t *pgd, unsigned long addr, unsigned long end) static void mark_kernel_pgd(void) { - unsigned long addr, next; + unsigned long addr, next, max_addr; struct page *page; pgd_t *pgd; int i; addr = 0; + /* + * Figure out maximum virtual address accessible with the + * kernel ASCE. This is required to keep the page table walker + * from accessing non-existent entries. + */ + max_addr = (S390_lowcore.kernel_asce.val & _ASCE_TYPE_MASK) >> 2; + max_addr = 1UL << (max_addr * 11 + 31); pgd = pgd_offset_k(addr); do { - next = pgd_addr_end(addr, MODULES_END); + next = pgd_addr_end(addr, max_addr); if (pgd_none(*pgd)) continue; if (!pgd_folded(*pgd)) { page = phys_to_page(pgd_val(*pgd)); - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) set_bit(PG_arch_1, &page[i].flags); } mark_kernel_p4d(pgd, addr, next); - } while (pgd++, addr = next, addr != MODULES_END); + } while (pgd++, addr = next, addr != max_addr); } void __init cmma_init_nodat(void) @@ -181,6 +188,12 @@ void __init cmma_init_nodat(void) return; /* Mark pages used in kernel page tables */ mark_kernel_pgd(); + page = virt_to_page(&swapper_pg_dir); + for (i = 0; i < 4; i++) + set_bit(PG_arch_1, &page[i].flags); + page = virt_to_page(&invalid_pg_dir); + for (i = 0; i < 4; i++) + set_bit(PG_arch_1, &page[i].flags); /* Set all kernel pages not used for page tables to stable/no-dat */ for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, NULL) { diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index b87e96c64b61..631e3a4ee2de 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -75,7 +75,7 @@ static void pgt_set(unsigned long *old, unsigned long new, unsigned long addr, break; } table = (unsigned long *)((unsigned long)old & mask); - crdte(*old, new, table, dtt, addr, S390_lowcore.kernel_asce); + crdte(*old, new, table, dtt, addr, S390_lowcore.kernel_asce.val); } else if (MACHINE_HAS_IDTE) { cspg(old, *old, new); } else { diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c index 75e1039f2ec5..5488ae17318e 100644 --- a/arch/s390/mm/pgalloc.c +++ b/arch/s390/mm/pgalloc.c @@ -61,8 +61,8 @@ static void __crst_table_upgrade(void *arg) /* change all active ASCEs to avoid the creation of new TLBs */ if (current->active_mm == mm) { - S390_lowcore.user_asce = mm->context.asce; - __ctl_load(S390_lowcore.user_asce, 7, 7); + S390_lowcore.user_asce.val = mm->context.asce; + local_ctl_load(7, &S390_lowcore.user_asce); } __tlb_flush_local(); } @@ -145,6 +145,7 @@ struct page *page_table_alloc_pgste(struct mm_struct *mm) ptdesc = pagetable_alloc(GFP_KERNEL, 0); if (ptdesc) { table = (u64 *)ptdesc_to_virt(ptdesc); + arch_set_page_dat(virt_to_page(table), 0); memset64(table, _PAGE_INVALID, PTRS_PER_PTE); memset64(table + PTRS_PER_PTE, 0, PTRS_PER_PTE); } @@ -487,11 +488,10 @@ static unsigned long *base_crst_alloc(unsigned long val) unsigned long *table; struct ptdesc *ptdesc; - ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, CRST_ALLOC_ORDER); + ptdesc = pagetable_alloc(GFP_KERNEL, CRST_ALLOC_ORDER); if (!ptdesc) return NULL; table = ptdesc_address(ptdesc); - crst_table_init(table, val); return table; } diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 6957d2ed97bf..2e8a1064f103 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -45,8 +47,11 @@ void *vmem_crst_alloc(unsigned long val) unsigned long *table; table = vmem_alloc_pages(CRST_ALLOC_ORDER); - if (table) - crst_table_init(table, val); + if (!table) + return NULL; + crst_table_init(table, val); + if (slab_is_available()) + arch_set_page_dat(virt_to_page(table), CRST_ALLOC_ORDER); return table; } @@ -498,6 +503,8 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, return ret; } +#ifdef CONFIG_MEMORY_HOTPLUG + void vmemmap_free(unsigned long start, unsigned long end, struct vmem_altmap *altmap) { @@ -506,6 +513,8 @@ void vmemmap_free(unsigned long start, unsigned long end, mutex_unlock(&vmem_mutex); } +#endif + void vmem_remove_mapping(unsigned long start, unsigned long size) { mutex_lock(&vmem_mutex); @@ -659,7 +668,7 @@ void __init vmem_map_init(void) __set_memory_4k(__va(0), RELOC_HIDE(__va(0), ident_map_size)); } if (MACHINE_HAS_NX) - ctl_set_bit(0, 20); + system_ctl_set_bit(0, CR0_INSTRUCTION_EXEC_PROTECTION_BIT); pr_info("Write protected kernel read-only data: %luk\n", (unsigned long)(__end_rodata - _stext) >> 10); } diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index d34d5813d006..6fab5c085565 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -1094,7 +1094,7 @@ static int __init pci_base_init(void) if (MACHINE_HAS_PCI_MIO) { static_branch_enable(&have_mio); - ctl_set_bit(2, 5); + system_ctl_set_bit(2, CR2_MIO_ADDRESSING_BIT); } rc = zpci_debug_init(); diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index 55a9f8c3a150..779f1268286e 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -123,6 +123,7 @@ int macio_init(void) irq = irq_of_parse_and_map(adbs, 0); of_node_put(adbs); if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) { + iounmap(adb); printk(KERN_ERR "ADB: can't get irq %d\n", irq); return -EAGAIN; } diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c index 65c7f2d565d8..9418a9270d03 100644 --- a/drivers/s390/char/diag_ftp.c +++ b/drivers/s390/char/diag_ftp.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include "hmcdrv_ftp.h" diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 8f74db689a0c..d53ee34d398f 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -81,7 +81,7 @@ static inline void sclp_trace(int prio, char *id, u32 a, u64 b, bool err) struct sclp_trace_entry e; memset(&e, 0, sizeof(e)); - strncpy(e.id, id, sizeof(e.id)); + strtomem(e.id, id); e.a = a; e.b = b; debug_event(&sclp_debug, prio, &e, sizeof(e)); @@ -706,8 +706,8 @@ void sclp_sync_wait(void) { unsigned long long old_tick; + struct ctlreg cr0, cr0_sync; unsigned long flags; - unsigned long cr0, cr0_sync; static u64 sync_count; u64 timeout; int irq_context; @@ -732,10 +732,10 @@ sclp_sync_wait(void) /* Enable service-signal interruption, disable timer interrupts */ old_tick = local_tick_disable(); trace_hardirqs_on(); - __ctl_store(cr0, 0, 0); - cr0_sync = cr0 & ~CR0_IRQ_SUBCLASS_MASK; - cr0_sync |= 1UL << (63 - 54); - __ctl_load(cr0_sync, 0, 0); + local_ctl_store(0, &cr0); + cr0_sync.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK; + cr0_sync.val |= 1UL << (63 - 54); + local_ctl_load(0, &cr0_sync); __arch_local_irq_stosm(0x01); /* Loop until driver state indicates finished request */ while (sclp_running_state != sclp_running_state_idle) { @@ -745,7 +745,7 @@ sclp_sync_wait(void) cpu_relax(); } local_irq_disable(); - __ctl_load(cr0, 0, 0); + local_ctl_load(0, &cr0); if (!irq_context) _local_bh_enable(); local_tick_enable(old_tick); diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 8b4575a0db9f..11c428f4c7cf 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -353,7 +353,6 @@ static int sclp_mem_notifier(struct notifier_block *nb, sclp_mem_change_state(start, size, 0); break; default: - rc = -EINVAL; break; } mutex_unlock(&sclp_mem_mutex); diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index fdc8668f3fba..60a247fdb2a7 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index dbd5c53d8edf..9f6165cafdc3 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -31,11 +32,11 @@ void sclp_early_wait_irq(void) psw_t psw_ext_save, psw_wait; union ctlreg0 cr0, cr0_new; - __ctl_store(cr0.val, 0, 0); + local_ctl_store(0, &cr0.reg); cr0_new.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK; cr0_new.lap = 0; cr0_new.sssm = 1; - __ctl_load(cr0_new.val, 0, 0); + local_ctl_load(0, &cr0_new.reg); psw_ext_save = S390_lowcore.external_new_psw; psw_mask = __extract_psw(); @@ -58,7 +59,7 @@ void sclp_early_wait_irq(void) } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG); S390_lowcore.external_new_psw = psw_ext_save; - __ctl_load(cr0.val, 0, 0); + local_ctl_load(0, &cr0.reg); } int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb) diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 5440f285f349..675d7ed82356 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -334,7 +334,7 @@ static ssize_t chp_cmg_show(struct device *dev, struct device_attribute *attr, return 0; if (chp->cmg == -1) /* channel measurements not available */ return sprintf(buf, "unknown\n"); - return sprintf(buf, "%x\n", chp->cmg); + return sprintf(buf, "%d\n", chp->cmg); } static DEVICE_ATTR(cmg, 0444, chp_cmg_show, NULL); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 0abd77f4b664..f8b04ce61556 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -393,8 +393,8 @@ static void format_node_data(char *params, char *id, struct node_descriptor *nd) memset(id, 0, NODEID_LEN); if (nd->validity != ND_VALIDITY_VALID) { - strncpy(params, "n/a", PARAMS_LEN - 1); - strncpy(id, "n/a", NODEID_LEN - 1); + strscpy(params, "n/a", PARAMS_LEN); + strscpy(id, "n/a", NODEID_LEN); return; } @@ -881,8 +881,8 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable) secm_area->request.code = 0x0016; secm_area->key = PAGE_DEFAULT_KEY >> 4; - secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1; - secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2; + secm_area->cub_addr1 = virt_to_phys(css->cub_addr1); + secm_area->cub_addr2 = virt_to_phys(css->cub_addr2); secm_area->operation_code = enable ? 0 : 1; diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index 7b02a6349c4d..4916dd0a7eb1 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include "ioasm.h" static DEFINE_MUTEX(crw_handler_mutex); @@ -156,7 +156,7 @@ static int __init crw_machine_check_init(void) task = kthread_run(crw_collect_info, NULL, "kmcheck"); if (IS_ERR(task)) return PTR_ERR(task); - ctl_set_bit(14, 28); /* enable channel report MCH */ + system_ctl_set_bit(14, CR14_CHANNEL_REPORT_SUBMASK_BIT); return 0; } device_initcall(crw_machine_check_init); diff --git a/drivers/s390/cio/isc.c b/drivers/s390/cio/isc.c index 77fde9f5ea8b..dbc2ac7711e5 100644 --- a/drivers/s390/cio/isc.c +++ b/drivers/s390/cio/isc.c @@ -33,7 +33,7 @@ void isc_register(unsigned int isc) spin_lock(&isc_ref_lock); if (isc_refs[isc] == 0) - ctl_set_bit(6, 31 - isc); + system_ctl_set_bit(6, 31 - isc); isc_refs[isc]++; spin_unlock(&isc_ref_lock); } @@ -61,7 +61,7 @@ void isc_unregister(unsigned int isc) goto out_unlock; } if (isc_refs[isc] == 1) - ctl_clear_bit(6, 31 - isc); + system_ctl_clear_bit(6, 31 - isc); isc_refs[isc]--; out_unlock: spin_unlock(&isc_ref_lock); diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 339812efe822..d09e08b71cfb 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1865,15 +1865,18 @@ static inline void ap_scan_domains(struct ap_card *ac) } /* get it and thus adjust reference counter */ get_device(dev); - if (decfg) + if (decfg) { AP_DBF_INFO("%s(%d,%d) new (decfg) queue dev created\n", __func__, ac->id, dom); - else if (chkstop) + } else if (chkstop) { AP_DBF_INFO("%s(%d,%d) new (chkstop) queue dev created\n", __func__, ac->id, dom); - else + } else { + /* nudge the queue's state machine */ + ap_queue_init_state(aq); AP_DBF_INFO("%s(%d,%d) new queue dev created\n", __func__, ac->id, dom); + } goto put_dev_and_continue; } /* handle state changes on already existing queue device */ @@ -1895,10 +1898,8 @@ static inline void ap_scan_domains(struct ap_card *ac) } else if (!chkstop && aq->chkstop) { /* checkstop off */ aq->chkstop = false; - if (aq->dev_state > AP_DEV_STATE_UNINITIATED) { - aq->dev_state = AP_DEV_STATE_OPERATING; - aq->sm_state = AP_SM_STATE_RESET_START; - } + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) + _ap_queue_init_state(aq); spin_unlock_bh(&aq->lock); AP_DBF_DBG("%s(%d,%d) queue dev checkstop off\n", __func__, ac->id, dom); @@ -1922,10 +1923,8 @@ static inline void ap_scan_domains(struct ap_card *ac) } else if (!decfg && !aq->config) { /* config on this queue device */ aq->config = true; - if (aq->dev_state > AP_DEV_STATE_UNINITIATED) { - aq->dev_state = AP_DEV_STATE_OPERATING; - aq->sm_state = AP_SM_STATE_RESET_START; - } + if (aq->dev_state > AP_DEV_STATE_UNINITIATED) + _ap_queue_init_state(aq); spin_unlock_bh(&aq->lock); AP_DBF_DBG("%s(%d,%d) queue dev config on\n", __func__, ac->id, dom); diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index be54b070c031..359a35f894d5 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -207,6 +207,7 @@ struct ap_queue { bool chkstop; /* checkstop state */ ap_qid_t qid; /* AP queue id. */ bool interrupt; /* indicate if interrupts are enabled */ + bool se_bound; /* SE bound state */ unsigned int assoc_idx; /* SE association index */ int queue_count; /* # messages currently on AP queue. */ int pendingq_count; /* # requests on pendingq list. */ @@ -271,6 +272,7 @@ enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event); int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg); void ap_cancel_message(struct ap_queue *aq, struct ap_message *ap_msg); void ap_flush_queue(struct ap_queue *aq); +bool ap_queue_usable(struct ap_queue *aq); void *ap_airq_ptr(void); int ap_sb_available(void); @@ -287,6 +289,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type); void ap_queue_prepare_remove(struct ap_queue *aq); void ap_queue_remove(struct ap_queue *aq); void ap_queue_init_state(struct ap_queue *aq); +void _ap_queue_init_state(struct ap_queue *aq); struct ap_card *ap_card_create(int id, int queue_depth, int raw_type, int comp_type, unsigned int functions, int ml); diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 1336e632adc4..993240370ecf 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -33,6 +33,11 @@ static inline bool ap_q_supports_assoc(struct ap_queue *aq) return ap_test_bit(&aq->card->functions, AP_FUNC_EP11); } +static inline bool ap_q_needs_bind(struct ap_queue *aq) +{ + return ap_q_supports_bind(aq) && ap_sb_available(); +} + /** * ap_queue_enable_irq(): Enable interrupt support on this AP queue. * @aq: The AP queue @@ -304,6 +309,7 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq) aq->sm_state = AP_SM_STATE_RESET_WAIT; aq->interrupt = false; aq->rapq_fbit = 0; + aq->se_bound = false; return AP_SM_WAIT_LOW_TIMEOUT; default: aq->dev_state = AP_DEV_STATE_ERROR; @@ -868,7 +874,12 @@ static ssize_t se_bind_store(struct device *dev, } status = ap_bapq(aq->qid); spin_unlock_bh(&aq->lock); - if (status.response_code) { + if (!status.response_code) { + aq->se_bound = true; + AP_DBF_INFO("%s bapq(0x%02x.%04x) success\n", __func__, + AP_QID_CARD(aq->qid), + AP_QID_QUEUE(aq->qid)); + } else { AP_DBF_WARN("%s RC 0x%02x on bapq(0x%02x.%04x)\n", __func__, status.response_code, AP_QID_CARD(aq->qid), @@ -1073,6 +1084,42 @@ int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) } EXPORT_SYMBOL(ap_queue_message); +/** + * ap_queue_usable(): Check if queue is usable just now. + * @aq: The AP queue device to test for usability. + * This function is intended for the scheduler to query if it makes + * sense to enqueue a message into this AP queue device by calling + * ap_queue_message(). The perspective is very short-term as the + * state machine and device state(s) may change at any time. + */ +bool ap_queue_usable(struct ap_queue *aq) +{ + bool rc = true; + + spin_lock_bh(&aq->lock); + + /* check for not configured or checkstopped */ + if (!aq->config || aq->chkstop) { + rc = false; + goto unlock_and_out; + } + + /* device state needs to be ok */ + if (aq->dev_state != AP_DEV_STATE_OPERATING) { + rc = false; + goto unlock_and_out; + } + + /* SE guest's queues additionally need to be bound */ + if (ap_q_needs_bind(aq) && !aq->se_bound) + rc = false; + +unlock_and_out: + spin_unlock_bh(&aq->lock); + return rc; +} +EXPORT_SYMBOL(ap_queue_usable); + /** * ap_cancel_message(): Cancel a crypto request. * @aq: The AP device that has the message queued @@ -1160,14 +1207,19 @@ void ap_queue_remove(struct ap_queue *aq) spin_unlock_bh(&aq->lock); } -void ap_queue_init_state(struct ap_queue *aq) +void _ap_queue_init_state(struct ap_queue *aq) { - spin_lock_bh(&aq->lock); aq->dev_state = AP_DEV_STATE_OPERATING; aq->sm_state = AP_SM_STATE_RESET_START; aq->last_err_rc = 0; aq->assoc_idx = ASSOC_IDX_INVALID; ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL)); +} + +void ap_queue_init_state(struct ap_queue *aq) +{ + spin_lock_bh(&aq->lock); + _ap_queue_init_state(aq); spin_unlock_bh(&aq->lock); } EXPORT_SYMBOL(ap_queue_init_state); diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index ce04caa7913f..dcd6c7299fa9 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -693,7 +693,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->rsa_modexpo || - !zq->queue->config || zq->queue->chkstop) + !ap_queue_usable(zq->queue)) continue; /* check if device node has admission for this queue */ if (!zcrypt_check_queue(perms, @@ -798,7 +798,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->rsa_modexpo_crt || - !zq->queue->config || zq->queue->chkstop) + !ap_queue_usable(zq->queue)) continue; /* check if device node has admission for this queue */ if (!zcrypt_check_queue(perms, @@ -916,7 +916,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check for device usable and eligible */ if (!zq->online || !zq->ops->send_cprb || - !zq->queue->config || zq->queue->chkstop || + !ap_queue_usable(zq->queue) || (tdom != AUTOSEL_DOM && tdom != AP_QID_QUEUE(zq->queue->qid))) continue; @@ -1087,7 +1087,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->send_ep11_cprb || - !zq->queue->config || zq->queue->chkstop || + !ap_queue_usable(zq->queue) || (targets && !is_desired_ep11_queue(zq->queue->qid, target_num, targets))) @@ -1186,7 +1186,7 @@ static long zcrypt_rng(char *buffer) for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->rng || - !zq->queue->config || zq->queue->chkstop) + !ap_queue_usable(zq->queue)) continue; if (!zcrypt_queue_compare(zq, pref_zq, wgt, pref_wgt)) continue; diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 9cfce9ff2e65..5c4532ab0040 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -279,7 +279,11 @@ static const struct { { 1, "BSI2009" }, { 2, "FIPS2011" }, { 3, "BSI2011" }, + { 4, "SIGG-IMPORT" }, + { 5, "SIGG" }, { 6, "BSICC2017" }, + { 7, "FIPS2021" }, + { 8, "FIPS2024" }, { 0, NULL } }; diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index d36177e65a3d..a44fcfcec938 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h @@ -98,8 +98,22 @@ static inline int convert_error(struct zcrypt_queue *zq, case REP88_ERROR_MESSAGE_MALFORMD: /* 0x22 */ case REP88_ERROR_KEY_TYPE: /* 0x34 */ /* RY indicates malformed request */ - ZCRYPT_DBF_WARN("%s dev=%02x.%04x RY=0x%02x => rc=EINVAL\n", - __func__, card, queue, ehdr->reply_code); + if (ehdr->reply_code == REP82_ERROR_FILTERED_BY_HYPERVISOR && + ehdr->type == TYPE86_RSP_CODE) { + struct { + struct type86_hdr hdr; + struct type86_fmt2_ext fmt2; + } __packed * head = reply->msg; + unsigned int apfs = *((u32 *)head->fmt2.apfs); + + ZCRYPT_DBF_WARN("%s dev=%02x.%04x RY=0x%02x apfs=0x%x => rc=EINVAL\n", + __func__, card, queue, + ehdr->reply_code, apfs); + } else { + ZCRYPT_DBF_WARN("%s dev=%02x.%04x RY=0x%02x => rc=EINVAL\n", + __func__, card, queue, + ehdr->reply_code); + } return -EINVAL; case REP82_ERROR_MACHINE_FAILURE: /* 0x10 */ case REP82_ERROR_MESSAGE_TYPE: /* 0x20 */ diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c index 9729ce86db59..a877347d37d3 100644 --- a/drivers/soc/fsl/qe/qe_common.c +++ b/drivers/soc/fsl/qe/qe_common.c @@ -141,7 +141,7 @@ static s32 cpm_muram_alloc_common(unsigned long size, * * This function returns a non-negative offset into the muram area, or * a negative errno on failure. - * Use cpm_dpram_addr() to get the virtual address of the area. + * Use cpm_muram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ s32 cpm_muram_alloc(unsigned long size, unsigned long align) @@ -193,7 +193,7 @@ EXPORT_SYMBOL(cpm_muram_free); * @size: number of bytes to allocate * This function returns @offset if the area was available, a negative * errno otherwise. - * Use cpm_dpram_addr() to get the virtual address of the area. + * Use cpm_muram_addr() to get the virtual address of the area. * Use cpm_muram_free() to free the allocation. */ s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size) diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index 8c8d64e76103..f8a594a50ae6 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -2,8 +2,9 @@ /* * event_inode.c - part of tracefs, a pseudo file system for activating tracing * - * Copyright (C) 2020-23 VMware Inc, author: Steven Rostedt (VMware) + * Copyright (C) 2020-23 VMware Inc, author: Steven Rostedt * Copyright (C) 2020-23 VMware Inc, author: Ajay Kaher + * Copyright (C) 2023 Google, author: Steven Rostedt * * eventfs is used to dynamically create inodes and dentries based on the * meta data provided by the tracing system. @@ -23,48 +24,30 @@ #include #include "internal.h" -struct eventfs_inode { - struct list_head e_top_files; -}; +/* + * eventfs_mutex protects the eventfs_inode (ei) dentry. Any access + * to the ei->dentry must be done under this mutex and after checking + * if ei->is_freed is not set. The ei->dentry is released under the + * mutex at the same time ei->is_freed is set. If ei->is_freed is set + * then the ei->dentry is invalid. + */ +static DEFINE_MUTEX(eventfs_mutex); /* - * struct eventfs_file - hold the properties of the eventfs files and - * directories. - * @name: the name of the file or directory to create - * @d_parent: holds parent's dentry - * @dentry: once accessed holds dentry - * @list: file or directory to be added to parent directory - * @ei: list of files and directories within directory - * @fop: file_operations for file or directory - * @iop: inode_operations for file or directory - * @data: something that the caller will want to get to later on - * @mode: the permission that the file or directory should have + * The eventfs_inode (ei) itself is protected by SRCU. It is released from + * its parent's list and will have is_freed set (under eventfs_mutex). + * After the SRCU grace period is over, the ei may be freed. */ -struct eventfs_file { - const char *name; - struct dentry *d_parent; - struct dentry *dentry; - struct list_head list; - struct eventfs_inode *ei; - const struct file_operations *fop; - const struct inode_operations *iop; - /* - * Union - used for deletion - * @del_list: list of eventfs_file to delete - * @rcu: eventfs_file to delete in RCU - * @is_freed: node is freed if one of the above is set - */ - union { - struct list_head del_list; - struct rcu_head rcu; - unsigned long is_freed; - }; - void *data; - umode_t mode; +DEFINE_STATIC_SRCU(eventfs_srcu); + +/* Mode is unsigned short, use the upper bits for flags */ +enum { + EVENTFS_SAVE_MODE = BIT(16), + EVENTFS_SAVE_UID = BIT(17), + EVENTFS_SAVE_GID = BIT(18), }; -static DEFINE_MUTEX(eventfs_mutex); -DEFINE_STATIC_SRCU(eventfs_srcu); +#define EVENTFS_MODE_MASK (EVENTFS_SAVE_MODE - 1) static struct dentry *eventfs_root_lookup(struct inode *dir, struct dentry *dentry, @@ -73,8 +56,88 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file); static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx); static int eventfs_release(struct inode *inode, struct file *file); +static void update_attr(struct eventfs_attr *attr, struct iattr *iattr) +{ + unsigned int ia_valid = iattr->ia_valid; + + if (ia_valid & ATTR_MODE) { + attr->mode = (attr->mode & ~EVENTFS_MODE_MASK) | + (iattr->ia_mode & EVENTFS_MODE_MASK) | + EVENTFS_SAVE_MODE; + } + if (ia_valid & ATTR_UID) { + attr->mode |= EVENTFS_SAVE_UID; + attr->uid = iattr->ia_uid; + } + if (ia_valid & ATTR_GID) { + attr->mode |= EVENTFS_SAVE_GID; + attr->gid = iattr->ia_gid; + } +} + +static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry, + struct iattr *iattr) +{ + const struct eventfs_entry *entry; + struct eventfs_inode *ei; + const char *name; + int ret; + + mutex_lock(&eventfs_mutex); + ei = dentry->d_fsdata; + if (ei->is_freed) { + /* Do not allow changes if the event is about to be removed. */ + mutex_unlock(&eventfs_mutex); + return -ENODEV; + } + + /* Preallocate the children mode array if necessary */ + if (!(dentry->d_inode->i_mode & S_IFDIR)) { + if (!ei->entry_attrs) { + ei->entry_attrs = kzalloc(sizeof(*ei->entry_attrs) * ei->nr_entries, + GFP_KERNEL); + if (!ei->entry_attrs) { + ret = -ENOMEM; + goto out; + } + } + } + + ret = simple_setattr(idmap, dentry, iattr); + if (ret < 0) + goto out; + + /* + * If this is a dir, then update the ei cache, only the file + * mode is saved in the ei->m_children, and the ownership is + * determined by the parent directory. + */ + if (dentry->d_inode->i_mode & S_IFDIR) { + update_attr(&ei->attr, iattr); + + } else { + name = dentry->d_name.name; + + for (int i = 0; i < ei->nr_entries; i++) { + entry = &ei->entries[i]; + if (strcmp(name, entry->name) == 0) { + update_attr(&ei->entry_attrs[i], iattr); + break; + } + } + } + out: + mutex_unlock(&eventfs_mutex); + return ret; +} + static const struct inode_operations eventfs_root_dir_inode_operations = { .lookup = eventfs_root_lookup, + .setattr = eventfs_set_attr, +}; + +static const struct inode_operations eventfs_file_inode_operations = { + .setattr = eventfs_set_attr, }; static const struct file_operations eventfs_file_operations = { @@ -85,26 +148,40 @@ static const struct file_operations eventfs_file_operations = { .release = eventfs_release, }; +static void update_inode_attr(struct inode *inode, struct eventfs_attr *attr, umode_t mode) +{ + if (!attr) { + inode->i_mode = mode; + return; + } + + if (attr->mode & EVENTFS_SAVE_MODE) + inode->i_mode = attr->mode & EVENTFS_MODE_MASK; + else + inode->i_mode = mode; + + if (attr->mode & EVENTFS_SAVE_UID) + inode->i_uid = attr->uid; + + if (attr->mode & EVENTFS_SAVE_GID) + inode->i_gid = attr->gid; +} + /** * create_file - create a file in the tracefs filesystem * @name: the name of the file to create. * @mode: the permission that the file should have. + * @attr: saved attributes changed by user * @parent: parent dentry for this file. * @data: something that the caller will want to get to later on. * @fop: struct file_operations that should be used for this file. * - * This is the basic "create a file" function for tracefs. It allows for a - * wide range of flexibility in creating a file. - * - * This function will return a pointer to a dentry if it succeeds. This - * pointer must be passed to the tracefs_remove() function when the file is - * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here.) If an error occurs, %NULL will be returned. - * - * If tracefs is not enabled in the kernel, the value -%ENODEV will be - * returned. + * This function creates a dentry that represents a file in the eventsfs_inode + * directory. The inode.i_private pointer will point to @data in the open() + * call. */ static struct dentry *create_file(const char *name, umode_t mode, + struct eventfs_attr *attr, struct dentry *parent, void *data, const struct file_operations *fop) { @@ -118,6 +195,7 @@ static struct dentry *create_file(const char *name, umode_t mode, if (WARN_ON_ONCE(!S_ISREG(mode))) return NULL; + WARN_ON_ONCE(!parent); dentry = eventfs_start_creating(name, parent); if (IS_ERR(dentry)) @@ -127,7 +205,10 @@ static struct dentry *create_file(const char *name, umode_t mode, if (unlikely(!inode)) return eventfs_failed_creating(dentry); - inode->i_mode = mode; + /* If the user updated the directory's attributes, use them */ + update_inode_attr(inode, attr, mode); + + inode->i_op = &eventfs_file_inode_operations; inode->i_fop = fop; inode->i_private = data; @@ -140,28 +221,19 @@ static struct dentry *create_file(const char *name, umode_t mode, /** * create_dir - create a dir in the tracefs filesystem - * @name: the name of the file to create. + * @ei: the eventfs_inode that represents the directory to create * @parent: parent dentry for this file. - * @data: something that the caller will want to get to later on. * - * This is the basic "create a dir" function for eventfs. It allows for a - * wide range of flexibility in creating a dir. - * - * This function will return a pointer to a dentry if it succeeds. This - * pointer must be passed to the tracefs_remove() function when the file is - * to be removed (no automatic cleanup happens if your module is unloaded, - * you are responsible here.) If an error occurs, %NULL will be returned. - * - * If tracefs is not enabled in the kernel, the value -%ENODEV will be - * returned. + * This function will create a dentry for a directory represented by + * a eventfs_inode. */ -static struct dentry *create_dir(const char *name, struct dentry *parent, void *data) +static struct dentry *create_dir(struct eventfs_inode *ei, struct dentry *parent) { struct tracefs_inode *ti; struct dentry *dentry; struct inode *inode; - dentry = eventfs_start_creating(name, parent); + dentry = eventfs_start_creating(ei->name, parent); if (IS_ERR(dentry)) return dentry; @@ -169,10 +241,11 @@ static struct dentry *create_dir(const char *name, struct dentry *parent, void * if (unlikely(!inode)) return eventfs_failed_creating(dentry); - inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; + /* If the user updated the directory's attributes, use them */ + update_inode_attr(inode, &ei->attr, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); + inode->i_op = &eventfs_root_dir_inode_operations; inode->i_fop = &eventfs_file_operations; - inode->i_private = data; ti = get_tracefs(inode); ti->flags |= TRACEFS_EVENT_INODE; @@ -184,117 +257,198 @@ static struct dentry *create_dir(const char *name, struct dentry *parent, void * return eventfs_end_creating(dentry); } -/** - * eventfs_set_ef_status_free - set the ef->status to free - * @ti: the tracefs_inode of the dentry - * @dentry: dentry who's status to be freed - * - * eventfs_set_ef_status_free will be called if no more - * references remain - */ -void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry) +static void free_ei(struct eventfs_inode *ei) +{ + kfree_const(ei->name); + kfree(ei->d_children); + kfree(ei->entry_attrs); + kfree(ei); +} + +/** + * eventfs_set_ei_status_free - remove the dentry reference from an eventfs_inode + * @ti: the tracefs_inode of the dentry + * @dentry: dentry which has the reference to remove. + * + * Remove the association between a dentry from an eventfs_inode. + */ +void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry) { - struct tracefs_inode *ti_parent; struct eventfs_inode *ei; - struct eventfs_file *ef, *tmp; - - /* The top level events directory may be freed by this */ - if (unlikely(ti->flags & TRACEFS_EVENT_TOP_INODE)) { - LIST_HEAD(ef_del_list); - - mutex_lock(&eventfs_mutex); - - ei = ti->private; - - /* Record all the top level files */ - list_for_each_entry_srcu(ef, &ei->e_top_files, list, - lockdep_is_held(&eventfs_mutex)) { - list_add_tail(&ef->del_list, &ef_del_list); - } - - /* Nothing should access this, but just in case! */ - ti->private = NULL; - - mutex_unlock(&eventfs_mutex); - - /* Now safely free the top level files and their children */ - list_for_each_entry_safe(ef, tmp, &ef_del_list, del_list) { - list_del(&ef->del_list); - eventfs_remove(ef); - } - - kfree(ei); - return; - } + int i; mutex_lock(&eventfs_mutex); - ti_parent = get_tracefs(dentry->d_parent->d_inode); - if (!ti_parent || !(ti_parent->flags & TRACEFS_EVENT_INODE)) + ei = dentry->d_fsdata; + if (!ei) goto out; - ef = dentry->d_fsdata; - if (!ef) - goto out; - - /* - * If ef was freed, then the LSB bit is set for d_fsdata. - * But this should not happen, as it should still have a - * ref count that prevents it. Warn in case it does. - */ - if (WARN_ON_ONCE((unsigned long)ef & 1)) - goto out; + /* This could belong to one of the files of the ei */ + if (ei->dentry != dentry) { + for (i = 0; i < ei->nr_entries; i++) { + if (ei->d_children[i] == dentry) + break; + } + if (WARN_ON_ONCE(i == ei->nr_entries)) + goto out; + ei->d_children[i] = NULL; + } else if (ei->is_freed) { + free_ei(ei); + } else { + ei->dentry = NULL; + } dentry->d_fsdata = NULL; - ef->dentry = NULL; -out: + out: mutex_unlock(&eventfs_mutex); } /** - * eventfs_post_create_dir - post create dir routine - * @ef: eventfs_file of recently created dir + * create_file_dentry - create a dentry for a file of an eventfs_inode + * @ei: the eventfs_inode that the file will be created under + * @idx: the index into the d_children[] of the @ei + * @parent: The parent dentry of the created file. + * @name: The name of the file to create + * @mode: The mode of the file. + * @data: The data to use to set the inode of the file with on open() + * @fops: The fops of the file to be created. + * @lookup: If called by the lookup routine, in which case, dput() the created dentry. * - * Map the meta-data of files within an eventfs dir to their parent dentry - */ -static void eventfs_post_create_dir(struct eventfs_file *ef) -{ - struct eventfs_file *ef_child; - struct tracefs_inode *ti; - - /* srcu lock already held */ - /* fill parent-child relation */ - list_for_each_entry_srcu(ef_child, &ef->ei->e_top_files, list, - srcu_read_lock_held(&eventfs_srcu)) { - ef_child->d_parent = ef->dentry; - } - - ti = get_tracefs(ef->dentry->d_inode); - ti->private = ef->ei; -} - -/** - * create_dentry - helper function to create dentry - * @ef: eventfs_file of file or directory to create - * @parent: parent dentry - * @lookup: true if called from lookup routine - * - * Used to create a dentry for file/dir, executes post dentry creation routine + * Create a dentry for a file of an eventfs_inode @ei and place it into the + * address located at @e_dentry. If the @e_dentry already has a dentry, then + * just do a dget() on it and return. Otherwise create the dentry and attach it. */ static struct dentry * -create_dentry(struct eventfs_file *ef, struct dentry *parent, bool lookup) +create_file_dentry(struct eventfs_inode *ei, int idx, + struct dentry *parent, const char *name, umode_t mode, void *data, + const struct file_operations *fops, bool lookup) { - bool invalidate = false; + struct eventfs_attr *attr = NULL; + struct dentry **e_dentry = &ei->d_children[idx]; struct dentry *dentry; + bool invalidate = false; mutex_lock(&eventfs_mutex); - if (ef->is_freed) { + if (ei->is_freed) { mutex_unlock(&eventfs_mutex); return NULL; } - if (ef->dentry) { - dentry = ef->dentry; - /* On dir open, up the ref count */ + /* If the e_dentry already has a dentry, use it */ + if (*e_dentry) { + /* lookup does not need to up the ref count */ + if (!lookup) + dget(*e_dentry); + mutex_unlock(&eventfs_mutex); + return *e_dentry; + } + + /* ei->entry_attrs are protected by SRCU */ + if (ei->entry_attrs) + attr = &ei->entry_attrs[idx]; + + mutex_unlock(&eventfs_mutex); + + /* The lookup already has the parent->d_inode locked */ + if (!lookup) + inode_lock(parent->d_inode); + + dentry = create_file(name, mode, attr, parent, data, fops); + + if (!lookup) + inode_unlock(parent->d_inode); + + mutex_lock(&eventfs_mutex); + + if (IS_ERR_OR_NULL(dentry)) { + /* + * When the mutex was released, something else could have + * created the dentry for this e_dentry. In which case + * use that one. + * + * Note, with the mutex held, the e_dentry cannot have content + * and the ei->is_freed be true at the same time. + */ + dentry = *e_dentry; + if (WARN_ON_ONCE(dentry && ei->is_freed)) + dentry = NULL; + /* The lookup does not need to up the dentry refcount */ + if (dentry && !lookup) + dget(dentry); + mutex_unlock(&eventfs_mutex); + return dentry; + } + + if (!*e_dentry && !ei->is_freed) { + *e_dentry = dentry; + dentry->d_fsdata = ei; + } else { + /* + * Should never happen unless we get here due to being freed. + * Otherwise it means two dentries exist with the same name. + */ + WARN_ON_ONCE(!ei->is_freed); + invalidate = true; + } + mutex_unlock(&eventfs_mutex); + + if (invalidate) + d_invalidate(dentry); + + if (lookup || invalidate) + dput(dentry); + + return invalidate ? NULL : dentry; +} + +/** + * eventfs_post_create_dir - post create dir routine + * @ei: eventfs_inode of recently created dir + * + * Map the meta-data of files within an eventfs dir to their parent dentry + */ +static void eventfs_post_create_dir(struct eventfs_inode *ei) +{ + struct eventfs_inode *ei_child; + struct tracefs_inode *ti; + + lockdep_assert_held(&eventfs_mutex); + + /* srcu lock already held */ + /* fill parent-child relation */ + list_for_each_entry_srcu(ei_child, &ei->children, list, + srcu_read_lock_held(&eventfs_srcu)) { + ei_child->d_parent = ei->dentry; + } + + ti = get_tracefs(ei->dentry->d_inode); + ti->private = ei; +} + +/** + * create_dir_dentry - Create a directory dentry for the eventfs_inode + * @pei: The eventfs_inode parent of ei. + * @ei: The eventfs_inode to create the directory for + * @parent: The dentry of the parent of this directory + * @lookup: True if this is called by the lookup code + * + * This creates and attaches a directory dentry to the eventfs_inode @ei. + */ +static struct dentry * +create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, + struct dentry *parent, bool lookup) +{ + bool invalidate = false; + struct dentry *dentry = NULL; + + mutex_lock(&eventfs_mutex); + if (pei->is_freed || ei->is_freed) { + mutex_unlock(&eventfs_mutex); + return NULL; + } + if (ei->dentry) { + /* If the dentry already has a dentry, use it */ + dentry = ei->dentry; + /* lookup does not need to up the ref count */ if (!lookup) dget(dentry); mutex_unlock(&eventfs_mutex); @@ -302,42 +456,44 @@ create_dentry(struct eventfs_file *ef, struct dentry *parent, bool lookup) } mutex_unlock(&eventfs_mutex); + /* The lookup already has the parent->d_inode locked */ if (!lookup) inode_lock(parent->d_inode); - if (ef->ei) - dentry = create_dir(ef->name, parent, ef->data); - else - dentry = create_file(ef->name, ef->mode, parent, - ef->data, ef->fop); + dentry = create_dir(ei, parent); if (!lookup) inode_unlock(parent->d_inode); mutex_lock(&eventfs_mutex); - if (IS_ERR_OR_NULL(dentry)) { - /* If the ef was already updated get it */ - dentry = ef->dentry; + + if (IS_ERR_OR_NULL(dentry) && !ei->is_freed) { + /* + * When the mutex was released, something else could have + * created the dentry for this e_dentry. In which case + * use that one. + * + * Note, with the mutex held, the e_dentry cannot have content + * and the ei->is_freed be true at the same time. + */ + dentry = ei->dentry; if (dentry && !lookup) dget(dentry); mutex_unlock(&eventfs_mutex); return dentry; } - if (!ef->dentry && !ef->is_freed) { - ef->dentry = dentry; - if (ef->ei) - eventfs_post_create_dir(ef); - dentry->d_fsdata = ef; + if (!ei->dentry && !ei->is_freed) { + ei->dentry = dentry; + eventfs_post_create_dir(ei); + dentry->d_fsdata = ei; } else { - /* A race here, should try again (unless freed) */ - invalidate = true; - /* * Should never happen unless we get here due to being freed. * Otherwise it means two dentries exist with the same name. */ - WARN_ON_ONCE(!ef->is_freed); + WARN_ON_ONCE(!ei->is_freed); + invalidate = true; } mutex_unlock(&eventfs_mutex); if (invalidate) @@ -349,50 +505,90 @@ create_dentry(struct eventfs_file *ef, struct dentry *parent, bool lookup) return invalidate ? NULL : dentry; } -static bool match_event_file(struct eventfs_file *ef, const char *name) -{ - bool ret; - - mutex_lock(&eventfs_mutex); - ret = !ef->is_freed && strcmp(ef->name, name) == 0; - mutex_unlock(&eventfs_mutex); - - return ret; -} - /** * eventfs_root_lookup - lookup routine to create file/dir * @dir: in which a lookup is being done * @dentry: file/dir dentry - * @flags: to pass as flags parameter to simple lookup + * @flags: Just passed to simple_lookup() * - * Used to create a dynamic file/dir within @dir. Use the eventfs_inode - * list of meta data to find the information needed to create the file/dir. + * Used to create dynamic file/dir with-in @dir, search with-in @ei + * list, if @dentry found go ahead and create the file/dir */ + static struct dentry *eventfs_root_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { + const struct file_operations *fops; + const struct eventfs_entry *entry; + struct eventfs_inode *ei_child; struct tracefs_inode *ti; struct eventfs_inode *ei; - struct eventfs_file *ef; + struct dentry *ei_dentry = NULL; struct dentry *ret = NULL; + const char *name = dentry->d_name.name; + bool created = false; + umode_t mode; + void *data; int idx; + int i; + int r; ti = get_tracefs(dir); if (!(ti->flags & TRACEFS_EVENT_INODE)) return NULL; - ei = ti->private; + /* Grab srcu to prevent the ei from going away */ idx = srcu_read_lock(&eventfs_srcu); - list_for_each_entry_srcu(ef, &ei->e_top_files, list, + + /* + * Grab the eventfs_mutex to consistent value from ti->private. + * This s + */ + mutex_lock(&eventfs_mutex); + ei = READ_ONCE(ti->private); + if (ei && !ei->is_freed) + ei_dentry = READ_ONCE(ei->dentry); + mutex_unlock(&eventfs_mutex); + + if (!ei || !ei_dentry) + goto out; + + data = ei->data; + + list_for_each_entry_srcu(ei_child, &ei->children, list, srcu_read_lock_held(&eventfs_srcu)) { - if (!match_event_file(ef, dentry->d_name.name)) + if (strcmp(ei_child->name, name) != 0) continue; ret = simple_lookup(dir, dentry, flags); - create_dentry(ef, ef->d_parent, true); + create_dir_dentry(ei, ei_child, ei_dentry, true); + created = true; break; } + + if (created) + goto out; + + for (i = 0; i < ei->nr_entries; i++) { + entry = &ei->entries[i]; + if (strcmp(name, entry->name) == 0) { + void *cdata = data; + mutex_lock(&eventfs_mutex); + /* If ei->is_freed, then the event itself may be too */ + if (!ei->is_freed) + r = entry->callback(name, &mode, &cdata, &fops); + else + r = -1; + mutex_unlock(&eventfs_mutex); + if (r <= 0) + continue; + ret = simple_lookup(dir, dentry, flags); + create_file_dentry(ei, i, ei_dentry, name, mode, cdata, + fops, true); + break; + } + } + out: srcu_read_unlock(&eventfs_srcu, idx); return ret; } @@ -432,29 +628,48 @@ static int eventfs_release(struct inode *inode, struct file *file) return dcache_dir_close(inode, file); } +static int add_dentries(struct dentry ***dentries, struct dentry *d, int cnt) +{ + struct dentry **tmp; + + tmp = krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_KERNEL); + if (!tmp) + return -1; + tmp[cnt] = d; + tmp[cnt + 1] = NULL; + *dentries = tmp; + return 0; +} + /** * dcache_dir_open_wrapper - eventfs open wrapper * @inode: not used - * @file: dir to be opened (to create its child) + * @file: dir to be opened (to create it's children) * - * Used to dynamically create the file/dir within @file. @file is really a - * directory and all the files/dirs of the children within @file will be - * created. If any of the files/dirs have already been created, their - * reference count will be incremented. + * Used to dynamic create file/dir with-in @file, all the + * file/dir will be created. If already created then references + * will be increased */ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) { + const struct file_operations *fops; + const struct eventfs_entry *entry; + struct eventfs_inode *ei_child; struct tracefs_inode *ti; struct eventfs_inode *ei; - struct eventfs_file *ef; struct dentry_list *dlist; struct dentry **dentries = NULL; - struct dentry *dentry = file_dentry(file); + struct dentry *parent = file_dentry(file); struct dentry *d; struct inode *f_inode = file_inode(file); + const char *name = parent->d_name.name; + umode_t mode; + void *data; int cnt = 0; int idx; int ret; + int i; + int r; ti = get_tracefs(f_inode); if (!(ti->flags & TRACEFS_EVENT_INODE)) @@ -463,25 +678,56 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) if (WARN_ON_ONCE(file->private_data)) return -EINVAL; - dlist = kmalloc(sizeof(*dlist), GFP_KERNEL); - if (!dlist) - return -ENOMEM; - - ei = ti->private; idx = srcu_read_lock(&eventfs_srcu); - list_for_each_entry_srcu(ef, &ei->e_top_files, list, - srcu_read_lock_held(&eventfs_srcu)) { - d = create_dentry(ef, dentry, false); - if (d) { - struct dentry **tmp; - tmp = krealloc(dentries, sizeof(d) * (cnt + 2), GFP_KERNEL); - if (!tmp) + mutex_lock(&eventfs_mutex); + ei = READ_ONCE(ti->private); + mutex_unlock(&eventfs_mutex); + + if (!ei) { + srcu_read_unlock(&eventfs_srcu, idx); + return -EINVAL; + } + + + data = ei->data; + + dlist = kmalloc(sizeof(*dlist), GFP_KERNEL); + if (!dlist) { + srcu_read_unlock(&eventfs_srcu, idx); + return -ENOMEM; + } + + list_for_each_entry_srcu(ei_child, &ei->children, list, + srcu_read_lock_held(&eventfs_srcu)) { + d = create_dir_dentry(ei, ei_child, parent, false); + if (d) { + ret = add_dentries(&dentries, d, cnt); + if (ret < 0) + break; + cnt++; + } + } + + for (i = 0; i < ei->nr_entries; i++) { + void *cdata = data; + entry = &ei->entries[i]; + name = entry->name; + mutex_lock(&eventfs_mutex); + /* If ei->is_freed, then the event itself may be too */ + if (!ei->is_freed) + r = entry->callback(name, &mode, &cdata, &fops); + else + r = -1; + mutex_unlock(&eventfs_mutex); + if (r <= 0) + continue; + d = create_file_dentry(ei, i, parent, name, mode, cdata, fops, false); + if (d) { + ret = add_dentries(&dentries, d, cnt); + if (ret < 0) break; - tmp[cnt] = d; - tmp[cnt + 1] = NULL; cnt++; - dentries = tmp; } } srcu_read_unlock(&eventfs_srcu, idx); @@ -514,63 +760,104 @@ static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx) } /** - * eventfs_prepare_ef - helper function to prepare eventfs_file - * @name: the name of the file/directory to create. - * @mode: the permission that the file should have. - * @fop: struct file_operations that should be used for this file/directory. - * @iop: struct inode_operations that should be used for this file/directory. - * @data: something that the caller will want to get to later on. The - * inode.i_private pointer will point to this value on the open() call. + * eventfs_create_dir - Create the eventfs_inode for this directory + * @name: The name of the directory to create. + * @parent: The eventfs_inode of the parent directory. + * @entries: A list of entries that represent the files under this directory + * @size: The number of @entries + * @data: The default data to pass to the files (an entry may override it). * - * This function allocates and fills the eventfs_file structure. + * This function creates the descriptor to represent a directory in the + * eventfs. This descriptor is an eventfs_inode, and it is returned to be + * used to create other children underneath. + * + * The @entries is an array of eventfs_entry structures which has: + * const char *name + * eventfs_callback callback; + * + * The name is the name of the file, and the callback is a pointer to a function + * that will be called when the file is reference (either by lookup or by + * reading a directory). The callback is of the prototype: + * + * int callback(const char *name, umode_t *mode, void **data, + * const struct file_operations **fops); + * + * When a file needs to be created, this callback will be called with + * name = the name of the file being created (so that the same callback + * may be used for multiple files). + * mode = a place to set the file's mode + * data = A pointer to @data, and the callback may replace it, which will + * cause the file created to pass the new data to the open() call. + * fops = the fops to use for the created file. + * + * NB. @callback is called while holding internal locks of the eventfs + * system. The callback must not call any code that might also call into + * the tracefs or eventfs system or it will risk creating a deadlock. */ -static struct eventfs_file *eventfs_prepare_ef(const char *name, umode_t mode, - const struct file_operations *fop, - const struct inode_operations *iop, - void *data) +struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode *parent, + const struct eventfs_entry *entries, + int size, void *data) { - struct eventfs_file *ef; + struct eventfs_inode *ei; - ef = kzalloc(sizeof(*ef), GFP_KERNEL); - if (!ef) + if (!parent) + return ERR_PTR(-EINVAL); + + ei = kzalloc(sizeof(*ei), GFP_KERNEL); + if (!ei) return ERR_PTR(-ENOMEM); - ef->name = kstrdup(name, GFP_KERNEL); - if (!ef->name) { - kfree(ef); + ei->name = kstrdup_const(name, GFP_KERNEL); + if (!ei->name) { + kfree(ei); return ERR_PTR(-ENOMEM); } - if (S_ISDIR(mode)) { - ef->ei = kzalloc(sizeof(*ef->ei), GFP_KERNEL); - if (!ef->ei) { - kfree(ef->name); - kfree(ef); + if (size) { + ei->d_children = kzalloc(sizeof(*ei->d_children) * size, GFP_KERNEL); + if (!ei->d_children) { + kfree_const(ei->name); + kfree(ei); return ERR_PTR(-ENOMEM); } - INIT_LIST_HEAD(&ef->ei->e_top_files); - } else { - ef->ei = NULL; } - ef->iop = iop; - ef->fop = fop; - ef->mode = mode; - ef->data = data; - return ef; + ei->entries = entries; + ei->nr_entries = size; + ei->data = data; + INIT_LIST_HEAD(&ei->children); + INIT_LIST_HEAD(&ei->list); + + mutex_lock(&eventfs_mutex); + if (!parent->is_freed) { + list_add_tail(&ei->list, &parent->children); + ei->d_parent = parent->dentry; + } + mutex_unlock(&eventfs_mutex); + + /* Was the parent freed? */ + if (list_empty(&ei->list)) { + free_ei(ei); + ei = NULL; + } + return ei; } /** - * eventfs_create_events_dir - create the trace event structure - * @name: the name of the directory to create. - * @parent: parent dentry for this file. This should be a directory dentry - * if set. If this parameter is NULL, then the directory will be - * created in the root of the tracefs filesystem. + * eventfs_create_events_dir - create the top level events directory + * @name: The name of the top level directory to create. + * @parent: Parent dentry for this file in the tracefs directory. + * @entries: A list of entries that represent the files under this directory + * @size: The number of @entries + * @data: The default data to pass to the files (an entry may override it). * * This function creates the top of the trace event directory. + * + * See eventfs_create_dir() for use of @entries. */ -struct dentry *eventfs_create_events_dir(const char *name, - struct dentry *parent) +struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry *parent, + const struct eventfs_entry *entries, + int size, void *data) { struct dentry *dentry = tracefs_start_creating(name, parent); struct eventfs_inode *ei; @@ -581,19 +868,32 @@ struct dentry *eventfs_create_events_dir(const char *name, return NULL; if (IS_ERR(dentry)) - return dentry; + return ERR_CAST(dentry); ei = kzalloc(sizeof(*ei), GFP_KERNEL); if (!ei) - return ERR_PTR(-ENOMEM); + goto fail_ei; + inode = tracefs_get_inode(dentry->d_sb); - if (unlikely(!inode)) { - kfree(ei); - tracefs_failed_creating(dentry); - return ERR_PTR(-ENOMEM); + if (unlikely(!inode)) + goto fail; + + if (size) { + ei->d_children = kzalloc(sizeof(*ei->d_children) * size, GFP_KERNEL); + if (!ei->d_children) + goto fail; } - INIT_LIST_HEAD(&ei->e_top_files); + ei->dentry = dentry; + ei->entries = entries; + ei->nr_entries = size; + ei->data = data; + ei->name = kstrdup_const(name, GFP_KERNEL); + if (!ei->name) + goto fail; + + INIT_LIST_HEAD(&ei->children); + INIT_LIST_HEAD(&ei->list); ti = get_tracefs(inode); ti->flags |= TRACEFS_EVENT_INODE | TRACEFS_EVENT_TOP_INODE; @@ -603,198 +903,97 @@ struct dentry *eventfs_create_events_dir(const char *name, inode->i_op = &eventfs_root_dir_inode_operations; inode->i_fop = &eventfs_file_operations; + dentry->d_fsdata = ei; + /* directory inodes start off with i_nlink == 2 (for "." entry) */ inc_nlink(inode); d_instantiate(dentry, inode); inc_nlink(dentry->d_parent->d_inode); fsnotify_mkdir(dentry->d_parent->d_inode, dentry); - return tracefs_end_creating(dentry); + tracefs_end_creating(dentry); + + return ei; + + fail: + kfree(ei->d_children); + kfree(ei); + fail_ei: + tracefs_failed_creating(dentry); + return ERR_PTR(-ENOMEM); } -/** - * eventfs_add_subsystem_dir - add eventfs subsystem_dir to list to create later - * @name: the name of the file to create. - * @parent: parent dentry for this dir. - * - * This function adds eventfs subsystem dir to list. - * And all these dirs are created on the fly when they are looked up, - * and the dentry and inodes will be removed when they are done. - */ -struct eventfs_file *eventfs_add_subsystem_dir(const char *name, - struct dentry *parent) +static LLIST_HEAD(free_list); + +static void eventfs_workfn(struct work_struct *work) { - struct tracefs_inode *ti_parent; - struct eventfs_inode *ei_parent; - struct eventfs_file *ef; + struct eventfs_inode *ei, *tmp; + struct llist_node *llnode; - if (security_locked_down(LOCKDOWN_TRACEFS)) - return NULL; - - if (!parent) - return ERR_PTR(-EINVAL); - - ti_parent = get_tracefs(parent->d_inode); - ei_parent = ti_parent->private; - - ef = eventfs_prepare_ef(name, S_IFDIR, NULL, NULL, NULL); - if (IS_ERR(ef)) - return ef; - - mutex_lock(&eventfs_mutex); - list_add_tail(&ef->list, &ei_parent->e_top_files); - ef->d_parent = parent; - mutex_unlock(&eventfs_mutex); - return ef; + llnode = llist_del_all(&free_list); + llist_for_each_entry_safe(ei, tmp, llnode, llist) { + /* This dput() matches the dget() from unhook_dentry() */ + for (int i = 0; i < ei->nr_entries; i++) { + if (ei->d_children[i]) + dput(ei->d_children[i]); + } + /* This should only get here if it had a dentry */ + if (!WARN_ON_ONCE(!ei->dentry)) + dput(ei->dentry); + } } -/** - * eventfs_add_dir - add eventfs dir to list to create later - * @name: the name of the file to create. - * @ef_parent: parent eventfs_file for this dir. - * - * This function adds eventfs dir to list. - * And all these dirs are created on the fly when they are looked up, - * and the dentry and inodes will be removed when they are done. - */ -struct eventfs_file *eventfs_add_dir(const char *name, - struct eventfs_file *ef_parent) +static DECLARE_WORK(eventfs_work, eventfs_workfn); + +static void free_rcu_ei(struct rcu_head *head) { - struct eventfs_file *ef; + struct eventfs_inode *ei = container_of(head, struct eventfs_inode, rcu); - if (security_locked_down(LOCKDOWN_TRACEFS)) - return NULL; + if (ei->dentry) { + /* Do not free the ei until all references of dentry are gone */ + if (llist_add(&ei->llist, &free_list)) + queue_work(system_unbound_wq, &eventfs_work); + return; + } - if (!ef_parent) - return ERR_PTR(-EINVAL); + /* If the ei doesn't have a dentry, neither should its children */ + for (int i = 0; i < ei->nr_entries; i++) { + WARN_ON_ONCE(ei->d_children[i]); + } - ef = eventfs_prepare_ef(name, S_IFDIR, NULL, NULL, NULL); - if (IS_ERR(ef)) - return ef; - - mutex_lock(&eventfs_mutex); - list_add_tail(&ef->list, &ef_parent->ei->e_top_files); - ef->d_parent = ef_parent->dentry; - mutex_unlock(&eventfs_mutex); - return ef; + free_ei(ei); } -/** - * eventfs_add_events_file - add the data needed to create a file for later reference - * @name: the name of the file to create. - * @mode: the permission that the file should have. - * @parent: parent dentry for this file. - * @data: something that the caller will want to get to later on. - * @fop: struct file_operations that should be used for this file. - * - * This function is used to add the information needed to create a - * dentry/inode within the top level events directory. The file created - * will have the @mode permissions. The @data will be used to fill the - * inode.i_private when the open() call is done. The dentry and inodes are - * all created when they are referenced, and removed when they are no - * longer referenced. - */ -int eventfs_add_events_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fop) +static void unhook_dentry(struct dentry *dentry) { - struct tracefs_inode *ti; - struct eventfs_inode *ei; - struct eventfs_file *ef; + if (!dentry) + return; + /* + * Need to add a reference to the dentry that is expected by + * simple_recursive_removal(), which will include a dput(). + */ + dget(dentry); - if (security_locked_down(LOCKDOWN_TRACEFS)) - return -ENODEV; - - if (!parent) - return -EINVAL; - - if (!(mode & S_IFMT)) - mode |= S_IFREG; - - if (!parent->d_inode) - return -EINVAL; - - ti = get_tracefs(parent->d_inode); - if (!(ti->flags & TRACEFS_EVENT_INODE)) - return -EINVAL; - - ei = ti->private; - ef = eventfs_prepare_ef(name, mode, fop, NULL, data); - - if (IS_ERR(ef)) - return -ENOMEM; - - mutex_lock(&eventfs_mutex); - list_add_tail(&ef->list, &ei->e_top_files); - ef->d_parent = parent; - mutex_unlock(&eventfs_mutex); - return 0; -} - -/** - * eventfs_add_file - add eventfs file to list to create later - * @name: the name of the file to create. - * @mode: the permission that the file should have. - * @ef_parent: parent eventfs_file for this file. - * @data: something that the caller will want to get to later on. - * @fop: struct file_operations that should be used for this file. - * - * This function is used to add the information needed to create a - * file within a subdirectory of the events directory. The file created - * will have the @mode permissions. The @data will be used to fill the - * inode.i_private when the open() call is done. The dentry and inodes are - * all created when they are referenced, and removed when they are no - * longer referenced. - */ -int eventfs_add_file(const char *name, umode_t mode, - struct eventfs_file *ef_parent, - void *data, - const struct file_operations *fop) -{ - struct eventfs_file *ef; - - if (security_locked_down(LOCKDOWN_TRACEFS)) - return -ENODEV; - - if (!ef_parent) - return -EINVAL; - - if (!(mode & S_IFMT)) - mode |= S_IFREG; - - ef = eventfs_prepare_ef(name, mode, fop, NULL, data); - if (IS_ERR(ef)) - return -ENOMEM; - - mutex_lock(&eventfs_mutex); - list_add_tail(&ef->list, &ef_parent->ei->e_top_files); - ef->d_parent = ef_parent->dentry; - mutex_unlock(&eventfs_mutex); - return 0; -} - -static void free_ef(struct rcu_head *head) -{ - struct eventfs_file *ef = container_of(head, struct eventfs_file, rcu); - - kfree(ef->name); - kfree(ef->ei); - kfree(ef); + /* + * Also add a reference for the dput() in eventfs_workfn(). + * That is required as that dput() will free the ei after + * the SRCU grace period is over. + */ + dget(dentry); } /** * eventfs_remove_rec - remove eventfs dir or file from list - * @ef: eventfs_file to be removed. - * @head: to create list of eventfs_file to be deleted - * @level: to check recursion depth + * @ei: eventfs_inode to be removed. + * @level: prevent recursion from going more than 3 levels deep. * - * The helper function eventfs_remove_rec() is used to clean up and free the - * associated data from eventfs for both of the added functions. + * This function recursively removes eventfs_inodes which + * contains info of files and/or directories. */ -static void eventfs_remove_rec(struct eventfs_file *ef, struct list_head *head, int level) +static void eventfs_remove_rec(struct eventfs_inode *ei, int level) { - struct eventfs_file *ef_child; + struct eventfs_inode *ei_child; - if (!ef) + if (!ei) return; /* * Check recursion depth. It should never be greater than 3: @@ -806,100 +1005,76 @@ static void eventfs_remove_rec(struct eventfs_file *ef, struct list_head *head, if (WARN_ON_ONCE(level > 3)) return; - if (ef->ei) { - /* search for nested folders or files */ - list_for_each_entry_srcu(ef_child, &ef->ei->e_top_files, list, - lockdep_is_held(&eventfs_mutex)) { - eventfs_remove_rec(ef_child, head, level + 1); + /* search for nested folders or files */ + list_for_each_entry_srcu(ei_child, &ei->children, list, + lockdep_is_held(&eventfs_mutex)) { + /* Children only have dentry if parent does */ + WARN_ON_ONCE(ei_child->dentry && !ei->dentry); + eventfs_remove_rec(ei_child, level + 1); + } + + + ei->is_freed = 1; + + for (int i = 0; i < ei->nr_entries; i++) { + if (ei->d_children[i]) { + /* Children only have dentry if parent does */ + WARN_ON_ONCE(!ei->dentry); + unhook_dentry(ei->d_children[i]); } } - list_del_rcu(&ef->list); - list_add_tail(&ef->del_list, head); + unhook_dentry(ei->dentry); + + list_del_rcu(&ei->list); + call_srcu(&eventfs_srcu, &ei->rcu, free_rcu_ei); } /** - * eventfs_remove - remove eventfs dir or file from list - * @ef: eventfs_file to be removed. + * eventfs_remove_dir - remove eventfs dir or file from list + * @ei: eventfs_inode to be removed. * * This function acquire the eventfs_mutex lock and call eventfs_remove_rec() */ -void eventfs_remove(struct eventfs_file *ef) +void eventfs_remove_dir(struct eventfs_inode *ei) { - struct eventfs_file *tmp; - LIST_HEAD(ef_del_list); - struct dentry *dentry_list = NULL; struct dentry *dentry; - if (!ef) + if (!ei) return; mutex_lock(&eventfs_mutex); - eventfs_remove_rec(ef, &ef_del_list, 0); - list_for_each_entry_safe(ef, tmp, &ef_del_list, del_list) { - if (ef->dentry) { - unsigned long ptr = (unsigned long)dentry_list; - - /* Keep the dentry from being freed yet */ - dget(ef->dentry); - - /* - * Paranoid: The dget() above should prevent the dentry - * from being freed and calling eventfs_set_ef_status_free(). - * But just in case, set the link list LSB pointer to 1 - * and have eventfs_set_ef_status_free() check that to - * make sure that if it does happen, it will not think - * the d_fsdata is an event_file. - * - * For this to work, no event_file should be allocated - * on a odd space, as the ef should always be allocated - * to be at least word aligned. Check for that too. - */ - WARN_ON_ONCE(ptr & 1); - - ef->dentry->d_fsdata = (void *)(ptr | 1); - dentry_list = ef->dentry; - ef->dentry = NULL; - } - call_srcu(&eventfs_srcu, &ef->rcu, free_ef); - } + dentry = ei->dentry; + eventfs_remove_rec(ei, 0); mutex_unlock(&eventfs_mutex); - while (dentry_list) { - unsigned long ptr; - - dentry = dentry_list; - ptr = (unsigned long)dentry->d_fsdata & ~1UL; - dentry_list = (struct dentry *)ptr; - dentry->d_fsdata = NULL; - d_invalidate(dentry); - mutex_lock(&eventfs_mutex); - /* dentry should now have at least a single reference */ - WARN_ONCE((int)d_count(dentry) < 1, - "dentry %p less than one reference (%d) after invalidate\n", - dentry, d_count(dentry)); - mutex_unlock(&eventfs_mutex); - dput(dentry); - } + /* + * If any of the ei children has a dentry, then the ei itself + * must have a dentry. + */ + if (dentry) + simple_recursive_removal(dentry, NULL); } /** - * eventfs_remove_events_dir - remove eventfs dir or file from list - * @dentry: events's dentry to be removed. + * eventfs_remove_events_dir - remove the top level eventfs directory + * @ei: the event_inode returned by eventfs_create_events_dir(). * - * This function remove events main directory + * This function removes the events main directory */ -void eventfs_remove_events_dir(struct dentry *dentry) +void eventfs_remove_events_dir(struct eventfs_inode *ei) { - struct tracefs_inode *ti; + struct dentry *dentry; - if (!dentry || !dentry->d_inode) - return; + dentry = ei->dentry; + eventfs_remove_dir(ei); - ti = get_tracefs(dentry->d_inode); - if (!ti || !(ti->flags & TRACEFS_EVENT_INODE)) - return; - - d_invalidate(dentry); + /* + * Matches the dget() done by tracefs_start_creating() + * in eventfs_create_events_dir() when it the dentry was + * created. In other words, it's a normal dentry that + * sticks around while the other ei->dentry are created + * and destroyed dynamically. + */ dput(dentry); } diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c index 429603d865a9..5b54948514fe 100644 --- a/fs/tracefs/inode.c +++ b/fs/tracefs/inode.c @@ -385,7 +385,7 @@ static void tracefs_dentry_iput(struct dentry *dentry, struct inode *inode) ti = get_tracefs(inode); if (ti && ti->flags & TRACEFS_EVENT_INODE) - eventfs_set_ef_status_free(ti, dentry); + eventfs_set_ei_status_free(ti, dentry); iput(inode); } diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h index 4f2e49e2197b..ccee18ca66c7 100644 --- a/fs/tracefs/internal.h +++ b/fs/tracefs/internal.h @@ -13,6 +13,58 @@ struct tracefs_inode { struct inode vfs_inode; }; +/* + * struct eventfs_attr - cache the mode and ownership of a eventfs entry + * @mode: saved mode plus flags of what is saved + * @uid: saved uid if changed + * @gid: saved gid if changed + */ +struct eventfs_attr { + int mode; + kuid_t uid; + kgid_t gid; +}; + +/* + * struct eventfs_inode - hold the properties of the eventfs directories. + * @list: link list into the parent directory + * @entries: the array of entries representing the files in the directory + * @name: the name of the directory to create + * @children: link list into the child eventfs_inode + * @dentry: the dentry of the directory + * @d_parent: pointer to the parent's dentry + * @d_children: The array of dentries to represent the files when created + * @entry_attrs: Saved mode and ownership of the @d_children + * @attr: Saved mode and ownership of eventfs_inode itself + * @data: The private data to pass to the callbacks + * @is_freed: Flag set if the eventfs is on its way to be freed + * Note if is_freed is set, then dentry is corrupted. + * @nr_entries: The number of items in @entries + */ +struct eventfs_inode { + struct list_head list; + const struct eventfs_entry *entries; + const char *name; + struct list_head children; + struct dentry *dentry; /* Check is_freed to access */ + struct dentry *d_parent; + struct dentry **d_children; + struct eventfs_attr *entry_attrs; + struct eventfs_attr attr; + void *data; + /* + * Union - used for deletion + * @llist: for calling dput() if needed after RCU + * @rcu: eventfs_inode to delete in RCU + */ + union { + struct llist_node llist; + struct rcu_head rcu; + }; + unsigned int is_freed:1; + unsigned int nr_entries:31; +}; + static inline struct tracefs_inode *get_tracefs(const struct inode *inode) { return container_of(inode, struct tracefs_inode, vfs_inode); @@ -25,6 +77,6 @@ struct inode *tracefs_get_inode(struct super_block *sb); struct dentry *eventfs_start_creating(const char *name, struct dentry *parent); struct dentry *eventfs_failed_creating(struct dentry *dentry); struct dentry *eventfs_end_creating(struct dentry *dentry); -void eventfs_set_ef_status_free(struct tracefs_inode *ti, struct dentry *dentry); +void eventfs_set_ei_status_free(struct tracefs_inode *ti, struct dentry *dentry); #endif /* _TRACEFS_INTERNAL_H */ diff --git a/include/linux/bitmap-str.h b/include/linux/bitmap-str.h new file mode 100644 index 000000000000..17caeca94cab --- /dev/null +++ b/include/linux/bitmap-str.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_BITMAP_STR_H +#define __LINUX_BITMAP_STR_H + +int bitmap_parse_user(const char __user *ubuf, unsigned int ulen, unsigned long *dst, int nbits); +int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp, int nmaskbits); +extern int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp, + int nmaskbits, loff_t off, size_t count); +extern int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp, + int nmaskbits, loff_t off, size_t count); +int bitmap_parse(const char *buf, unsigned int buflen, unsigned long *dst, int nbits); +int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits); +int bitmap_parselist_user(const char __user *ubuf, unsigned int ulen, + unsigned long *dst, int nbits); + +#endif /* __LINUX_BITMAP_STR_H */ diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 03644237e1ef..99451431e4d6 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -6,10 +6,12 @@ #include #include +#include #include #include #include #include +#include struct device; @@ -200,14 +202,6 @@ bitmap_find_next_zero_area(unsigned long *map, align_mask, 0); } -int bitmap_parse(const char *buf, unsigned int buflen, - unsigned long *dst, int nbits); -int bitmap_parse_user(const char __user *ubuf, unsigned int ulen, - unsigned long *dst, int nbits); -int bitmap_parselist(const char *buf, unsigned long *maskp, - int nmaskbits); -int bitmap_parselist_user(const char __user *ubuf, unsigned int ulen, - unsigned long *dst, int nbits); void bitmap_remap(unsigned long *dst, const unsigned long *src, const unsigned long *old, const unsigned long *new, unsigned int nbits); int bitmap_bitremap(int oldbit, @@ -216,23 +210,6 @@ void bitmap_onto(unsigned long *dst, const unsigned long *orig, const unsigned long *relmap, unsigned int bits); void bitmap_fold(unsigned long *dst, const unsigned long *orig, unsigned int sz, unsigned int nbits); -int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order); -void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order); -int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order); - -#ifdef __BIG_ENDIAN -void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits); -#else -#define bitmap_copy_le bitmap_copy -#endif -int bitmap_print_to_pagebuf(bool list, char *buf, - const unsigned long *maskp, int nmaskbits); - -extern int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp, - int nmaskbits, loff_t off, size_t count); - -extern int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp, - int nmaskbits, loff_t off, size_t count); #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1))) @@ -518,6 +495,66 @@ static inline void bitmap_next_set_region(unsigned long *bitmap, *re = find_next_zero_bit(bitmap, end, *rs + 1); } +/** + * bitmap_release_region - release allocated bitmap region + * @bitmap: array of unsigned longs corresponding to the bitmap + * @pos: beginning of bit region to release + * @order: region size (log base 2 of number of bits) to release + * + * This is the complement to __bitmap_find_free_region() and releases + * the found region (by clearing it in the bitmap). + */ +static inline void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order) +{ + bitmap_clear(bitmap, pos, BIT(order)); +} + +/** + * bitmap_allocate_region - allocate bitmap region + * @bitmap: array of unsigned longs corresponding to the bitmap + * @pos: beginning of bit region to allocate + * @order: region size (log base 2 of number of bits) to allocate + * + * Allocate (set bits in) a specified region of a bitmap. + * + * Returns: 0 on success, or %-EBUSY if specified region wasn't + * free (not all bits were zero). + */ +static inline int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order) +{ + unsigned int len = BIT(order); + + if (find_next_bit(bitmap, pos + len, pos) < pos + len) + return -EBUSY; + bitmap_set(bitmap, pos, len); + return 0; +} + +/** + * bitmap_find_free_region - find a contiguous aligned mem region + * @bitmap: array of unsigned longs corresponding to the bitmap + * @bits: number of bits in the bitmap + * @order: region size (log base 2 of number of bits) to find + * + * Find a region of free (zero) bits in a @bitmap of @bits bits and + * allocate them (set them to one). Only consider regions of length + * a power (@order) of two, aligned to that power of two, which + * makes the search algorithm much faster. + * + * Returns: the bit offset in bitmap of the allocated region, + * or -errno on failure. + */ +static inline int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order) +{ + unsigned int pos, end; /* scans bitmap by regions of size order */ + + for (pos = 0; (end = pos + BIT(order)) <= bits; pos = end) { + if (!bitmap_allocate_region(bitmap, pos, order)) + return pos; + } + return -ENOMEM; +} + /** * BITMAP_FROM_U64() - Represent u64 value in the format suitable for bitmap. * @n: u64 value diff --git a/include/linux/buildid.h b/include/linux/buildid.h index 3b7a0ff4642f..8a582d242f06 100644 --- a/include/linux/buildid.h +++ b/include/linux/buildid.h @@ -2,10 +2,11 @@ #ifndef _LINUX_BUILDID_H #define _LINUX_BUILDID_H -#include +#include #define BUILD_ID_SIZE_MAX 20 +struct vm_area_struct; int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size); int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size); diff --git a/include/linux/console.h b/include/linux/console.h index 7de11c763eb3..e4fc6f7c1496 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -156,6 +156,8 @@ static inline int con_debug_leave(void) * /dev/kmesg which requires a larger output buffer. * @CON_SUSPENDED: Indicates if a console is suspended. If true, the * printing callbacks must not be called. + * @CON_NBCON: Console can operate outside of the legacy style console_lock + * constraints. */ enum cons_flags { CON_PRINTBUFFER = BIT(0), @@ -166,6 +168,111 @@ enum cons_flags { CON_BRL = BIT(5), CON_EXTENDED = BIT(6), CON_SUSPENDED = BIT(7), + CON_NBCON = BIT(8), +}; + +/** + * struct nbcon_state - console state for nbcon consoles + * @atom: Compound of the state fields for atomic operations + * + * @req_prio: The priority of a handover request + * @prio: The priority of the current owner + * @unsafe: Console is busy in a non takeover region + * @unsafe_takeover: A hostile takeover in an unsafe state happened in the + * past. The console cannot be safe until re-initialized. + * @cpu: The CPU on which the owner runs + * + * To be used for reading and preparing of the value stored in the nbcon + * state variable @console::nbcon_state. + * + * The @prio and @req_prio fields are particularly important to allow + * spin-waiting to timeout and give up without the risk of a waiter being + * assigned the lock after giving up. + */ +struct nbcon_state { + union { + unsigned int atom; + struct { + unsigned int prio : 2; + unsigned int req_prio : 2; + unsigned int unsafe : 1; + unsigned int unsafe_takeover : 1; + unsigned int cpu : 24; + }; + }; +}; + +/* + * The nbcon_state struct is used to easily create and interpret values that + * are stored in the @console::nbcon_state variable. Ensure this struct stays + * within the size boundaries of the atomic variable's underlying type in + * order to avoid any accidental truncation. + */ +static_assert(sizeof(struct nbcon_state) <= sizeof(int)); + +/** + * nbcon_prio - console owner priority for nbcon consoles + * @NBCON_PRIO_NONE: Unused + * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage + * @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...) + * @NBCON_PRIO_PANIC: Panic output + * @NBCON_PRIO_MAX: The number of priority levels + * + * A higher priority context can takeover the console when it is + * in the safe state. The final attempt to flush consoles in panic() + * can be allowed to do so even in an unsafe state (Hope and pray). + */ +enum nbcon_prio { + NBCON_PRIO_NONE = 0, + NBCON_PRIO_NORMAL, + NBCON_PRIO_EMERGENCY, + NBCON_PRIO_PANIC, + NBCON_PRIO_MAX, +}; + +struct console; +struct printk_buffers; + +/** + * struct nbcon_context - Context for console acquire/release + * @console: The associated console + * @spinwait_max_us: Limit for spin-wait acquire + * @prio: Priority of the context + * @allow_unsafe_takeover: Allow performing takeover even if unsafe. Can + * be used only with NBCON_PRIO_PANIC @prio. It + * might cause a system freeze when the console + * is used later. + * @backlog: Ringbuffer has pending records + * @pbufs: Pointer to the text buffer for this context + * @seq: The sequence number to print for this context + */ +struct nbcon_context { + /* members set by caller */ + struct console *console; + unsigned int spinwait_max_us; + enum nbcon_prio prio; + unsigned int allow_unsafe_takeover : 1; + + /* members set by emit */ + unsigned int backlog : 1; + + /* members set by acquire */ + struct printk_buffers *pbufs; + u64 seq; +}; + +/** + * struct nbcon_write_context - Context handed to the nbcon write callbacks + * @ctxt: The core console context + * @outbuf: Pointer to the text buffer for output + * @len: Length to write + * @unsafe_takeover: If a hostile takeover in an unsafe state has occurred + */ +struct nbcon_write_context { + struct nbcon_context __private ctxt; + char *outbuf; + unsigned int len; + bool unsafe_takeover; }; /** @@ -187,6 +294,11 @@ enum cons_flags { * @dropped: Number of unreported dropped ringbuffer records * @data: Driver private data * @node: hlist node for the console list + * + * @write_atomic: Write callback for atomic context + * @nbcon_state: State for nbcon consoles + * @nbcon_seq: Sequence number of the next record for nbcon to print + * @pbufs: Pointer to nbcon private buffer */ struct console { char name[16]; @@ -206,6 +318,13 @@ struct console { unsigned long dropped; void *data; struct hlist_node node; + + /* nbcon console specific members */ + bool (*write_atomic)(struct console *con, + struct nbcon_write_context *wctxt); + atomic_t __private nbcon_state; + atomic_long_t __private nbcon_seq; + struct printk_buffers *pbufs; }; #ifdef CONFIG_LOCKDEP @@ -332,6 +451,16 @@ static inline bool console_is_registered(const struct console *con) lockdep_assert_console_list_lock_held(); \ hlist_for_each_entry(con, &console_list, node) +#ifdef CONFIG_PRINTK +extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); +extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); +extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); +#else +static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } +static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } +static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } +#endif + extern int console_set_on_cmdline; extern struct console *early_console; diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index f10fb87d49db..cfb545841a2c 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -4,7 +4,7 @@ /* * Cpumasks provide a bitmap suitable for representing the - * set of CPU's in a system, one bit position per CPU number. In general, + * set of CPUs in a system, one bit position per CPU number. In general, * only nr_cpu_ids (<= NR_CPUS) bits are valid. */ #include @@ -97,7 +97,7 @@ static inline void set_nr_cpu_ids(unsigned int nr) * * If !CONFIG_HOTPLUG_CPU, present == possible, and active == online. * - * The cpu_possible_mask is fixed at boot time, as the set of CPU id's + * The cpu_possible_mask is fixed at boot time, as the set of CPU IDs * that it is possible might ever be plugged in at anytime during the * life of that system boot. The cpu_present_mask is dynamic(*), * representing which CPUs are currently plugged in. And @@ -112,7 +112,7 @@ static inline void set_nr_cpu_ids(unsigned int nr) * hotplug, it's a copy of cpu_possible_mask, hence fixed at boot. * * Subtleties: - * 1) UP arch's (NR_CPUS == 1, CONFIG_SMP not defined) hardcode + * 1) UP ARCHes (NR_CPUS == 1, CONFIG_SMP not defined) hardcode * assumption that their single CPU is online. The UP * cpu_{online,possible,present}_masks are placebos. Changing them * will have no useful affect on the following num_*_cpus() @@ -155,7 +155,7 @@ static __always_inline unsigned int cpumask_check(unsigned int cpu) * cpumask_first - get the first cpu in a cpumask * @srcp: the cpumask pointer * - * Returns >= nr_cpu_ids if no cpus set. + * Return: >= nr_cpu_ids if no cpus set. */ static inline unsigned int cpumask_first(const struct cpumask *srcp) { @@ -166,7 +166,7 @@ static inline unsigned int cpumask_first(const struct cpumask *srcp) * cpumask_first_zero - get the first unset cpu in a cpumask * @srcp: the cpumask pointer * - * Returns >= nr_cpu_ids if all cpus are set. + * Return: >= nr_cpu_ids if all cpus are set. */ static inline unsigned int cpumask_first_zero(const struct cpumask *srcp) { @@ -178,7 +178,7 @@ static inline unsigned int cpumask_first_zero(const struct cpumask *srcp) * @srcp1: the first input * @srcp2: the second input * - * Returns >= nr_cpu_ids if no cpus set in both. See also cpumask_next_and(). + * Return: >= nr_cpu_ids if no cpus set in both. See also cpumask_next_and(). */ static inline unsigned int cpumask_first_and(const struct cpumask *srcp1, const struct cpumask *srcp2) @@ -190,7 +190,7 @@ unsigned int cpumask_first_and(const struct cpumask *srcp1, const struct cpumask * cpumask_last - get the last CPU in a cpumask * @srcp: - the cpumask pointer * - * Returns >= nr_cpumask_bits if no CPUs set. + * Return: >= nr_cpumask_bits if no CPUs set. */ static inline unsigned int cpumask_last(const struct cpumask *srcp) { @@ -199,10 +199,10 @@ static inline unsigned int cpumask_last(const struct cpumask *srcp) /** * cpumask_next - get the next cpu in a cpumask - * @n: the cpu prior to the place to search (ie. return will be > @n) + * @n: the cpu prior to the place to search (i.e. return will be > @n) * @srcp: the cpumask pointer * - * Returns >= nr_cpu_ids if no further cpus set. + * Return: >= nr_cpu_ids if no further cpus set. */ static inline unsigned int cpumask_next(int n, const struct cpumask *srcp) @@ -215,10 +215,10 @@ unsigned int cpumask_next(int n, const struct cpumask *srcp) /** * cpumask_next_zero - get the next unset cpu in a cpumask - * @n: the cpu prior to the place to search (ie. return will be > @n) + * @n: the cpu prior to the place to search (i.e. return will be > @n) * @srcp: the cpumask pointer * - * Returns >= nr_cpu_ids if no further cpus unset. + * Return: >= nr_cpu_ids if no further cpus unset. */ static inline unsigned int cpumask_next_zero(int n, const struct cpumask *srcp) { @@ -254,11 +254,11 @@ unsigned int cpumask_any_distribute(const struct cpumask *srcp); /** * cpumask_next_and - get the next cpu in *src1p & *src2p - * @n: the cpu prior to the place to search (ie. return will be > @n) + * @n: the cpu prior to the place to search (i.e. return will be > @n) * @src1p: the first cpumask pointer * @src2p: the second cpumask pointer * - * Returns >= nr_cpu_ids if no further cpus set in both. + * Return: >= nr_cpu_ids if no further cpus set in both. */ static inline unsigned int cpumask_next_and(int n, const struct cpumask *src1p, @@ -373,7 +373,7 @@ unsigned int __pure cpumask_next_wrap(int n, const struct cpumask *mask, int sta * @cpu: the cpu to ignore. * * Often used to find any cpu but smp_processor_id() in a mask. - * Returns >= nr_cpu_ids if no cpus set. + * Return: >= nr_cpu_ids if no cpus set. */ static inline unsigned int cpumask_any_but(const struct cpumask *mask, unsigned int cpu) @@ -388,11 +388,11 @@ unsigned int cpumask_any_but(const struct cpumask *mask, unsigned int cpu) } /** - * cpumask_nth - get the first cpu in a cpumask + * cpumask_nth - get the Nth cpu in a cpumask * @srcp: the cpumask pointer - * @cpu: the N'th cpu to find, starting from 0 + * @cpu: the Nth cpu to find, starting from 0 * - * Returns >= nr_cpu_ids if such cpu doesn't exist. + * Return: >= nr_cpu_ids if such cpu doesn't exist. */ static inline unsigned int cpumask_nth(unsigned int cpu, const struct cpumask *srcp) { @@ -400,12 +400,12 @@ static inline unsigned int cpumask_nth(unsigned int cpu, const struct cpumask *s } /** - * cpumask_nth_and - get the first cpu in 2 cpumasks + * cpumask_nth_and - get the Nth cpu in 2 cpumasks * @srcp1: the cpumask pointer * @srcp2: the cpumask pointer - * @cpu: the N'th cpu to find, starting from 0 + * @cpu: the Nth cpu to find, starting from 0 * - * Returns >= nr_cpu_ids if such cpu doesn't exist. + * Return: >= nr_cpu_ids if such cpu doesn't exist. */ static inline unsigned int cpumask_nth_and(unsigned int cpu, const struct cpumask *srcp1, @@ -416,12 +416,12 @@ unsigned int cpumask_nth_and(unsigned int cpu, const struct cpumask *srcp1, } /** - * cpumask_nth_andnot - get the first cpu set in 1st cpumask, and clear in 2nd. + * cpumask_nth_andnot - get the Nth cpu set in 1st cpumask, and clear in 2nd. * @srcp1: the cpumask pointer * @srcp2: the cpumask pointer - * @cpu: the N'th cpu to find, starting from 0 + * @cpu: the Nth cpu to find, starting from 0 * - * Returns >= nr_cpu_ids if such cpu doesn't exist. + * Return: >= nr_cpu_ids if such cpu doesn't exist. */ static inline unsigned int cpumask_nth_andnot(unsigned int cpu, const struct cpumask *srcp1, @@ -436,9 +436,9 @@ unsigned int cpumask_nth_andnot(unsigned int cpu, const struct cpumask *srcp1, * @srcp1: the cpumask pointer * @srcp2: the cpumask pointer * @srcp3: the cpumask pointer - * @cpu: the N'th cpu to find, starting from 0 + * @cpu: the Nth cpu to find, starting from 0 * - * Returns >= nr_cpu_ids if such cpu doesn't exist. + * Return: >= nr_cpu_ids if such cpu doesn't exist. */ static __always_inline unsigned int cpumask_nth_and_andnot(unsigned int cpu, const struct cpumask *srcp1, @@ -497,7 +497,7 @@ static __always_inline void __cpumask_clear_cpu(int cpu, struct cpumask *dstp) * @cpu: cpu number (< nr_cpu_ids) * @cpumask: the cpumask pointer * - * Returns true if @cpu is set in @cpumask, else returns false + * Return: true if @cpu is set in @cpumask, else returns false */ static __always_inline bool cpumask_test_cpu(int cpu, const struct cpumask *cpumask) { @@ -509,9 +509,9 @@ static __always_inline bool cpumask_test_cpu(int cpu, const struct cpumask *cpum * @cpu: cpu number (< nr_cpu_ids) * @cpumask: the cpumask pointer * - * Returns true if @cpu is set in old bitmap of @cpumask, else returns false - * * test_and_set_bit wrapper for cpumasks. + * + * Return: true if @cpu is set in old bitmap of @cpumask, else returns false */ static __always_inline bool cpumask_test_and_set_cpu(int cpu, struct cpumask *cpumask) { @@ -523,9 +523,9 @@ static __always_inline bool cpumask_test_and_set_cpu(int cpu, struct cpumask *cp * @cpu: cpu number (< nr_cpu_ids) * @cpumask: the cpumask pointer * - * Returns true if @cpu is set in old bitmap of @cpumask, else returns false - * * test_and_clear_bit wrapper for cpumasks. + * + * Return: true if @cpu is set in old bitmap of @cpumask, else returns false */ static __always_inline bool cpumask_test_and_clear_cpu(int cpu, struct cpumask *cpumask) { @@ -560,7 +560,7 @@ static inline void cpumask_clear(struct cpumask *dstp) * @src1p: the first input * @src2p: the second input * - * If *@dstp is empty, returns false, else returns true + * Return: false if *@dstp is empty, else returns true */ static inline bool cpumask_and(struct cpumask *dstp, const struct cpumask *src1p, @@ -603,7 +603,7 @@ static inline void cpumask_xor(struct cpumask *dstp, * @src1p: the first input * @src2p: the second input * - * If *@dstp is empty, returns false, else returns true + * Return: false if *@dstp is empty, else returns true */ static inline bool cpumask_andnot(struct cpumask *dstp, const struct cpumask *src1p, @@ -617,6 +617,8 @@ static inline bool cpumask_andnot(struct cpumask *dstp, * cpumask_equal - *src1p == *src2p * @src1p: the first input * @src2p: the second input + * + * Return: true if the cpumasks are equal, false if not */ static inline bool cpumask_equal(const struct cpumask *src1p, const struct cpumask *src2p) @@ -630,6 +632,9 @@ static inline bool cpumask_equal(const struct cpumask *src1p, * @src1p: the first input * @src2p: the second input * @src3p: the third input + * + * Return: true if first cpumask ORed with second cpumask == third cpumask, + * otherwise false */ static inline bool cpumask_or_equal(const struct cpumask *src1p, const struct cpumask *src2p, @@ -643,6 +648,9 @@ static inline bool cpumask_or_equal(const struct cpumask *src1p, * cpumask_intersects - (*src1p & *src2p) != 0 * @src1p: the first input * @src2p: the second input + * + * Return: true if first cpumask ANDed with second cpumask is non-empty, + * otherwise false */ static inline bool cpumask_intersects(const struct cpumask *src1p, const struct cpumask *src2p) @@ -656,7 +664,7 @@ static inline bool cpumask_intersects(const struct cpumask *src1p, * @src1p: the first input * @src2p: the second input * - * Returns true if *@src1p is a subset of *@src2p, else returns false + * Return: true if *@src1p is a subset of *@src2p, else returns false */ static inline bool cpumask_subset(const struct cpumask *src1p, const struct cpumask *src2p) @@ -668,6 +676,8 @@ static inline bool cpumask_subset(const struct cpumask *src1p, /** * cpumask_empty - *srcp == 0 * @srcp: the cpumask to that all cpus < nr_cpu_ids are clear. + * + * Return: true if srcp is empty (has no bits set), else false */ static inline bool cpumask_empty(const struct cpumask *srcp) { @@ -677,6 +687,8 @@ static inline bool cpumask_empty(const struct cpumask *srcp) /** * cpumask_full - *srcp == 0xFFFFFFFF... * @srcp: the cpumask to that all cpus < nr_cpu_ids are set. + * + * Return: true if srcp is full (has all bits set), else false */ static inline bool cpumask_full(const struct cpumask *srcp) { @@ -686,6 +698,8 @@ static inline bool cpumask_full(const struct cpumask *srcp) /** * cpumask_weight - Count of bits in *srcp * @srcp: the cpumask to count bits (< nr_cpu_ids) in. + * + * Return: count of bits set in *srcp */ static inline unsigned int cpumask_weight(const struct cpumask *srcp) { @@ -696,6 +710,8 @@ static inline unsigned int cpumask_weight(const struct cpumask *srcp) * cpumask_weight_and - Count of bits in (*srcp1 & *srcp2) * @srcp1: the cpumask to count bits (< nr_cpu_ids) in. * @srcp2: the cpumask to count bits (< nr_cpu_ids) in. + * + * Return: count of bits set in both *srcp1 and *srcp2 */ static inline unsigned int cpumask_weight_and(const struct cpumask *srcp1, const struct cpumask *srcp2) @@ -744,7 +760,7 @@ static inline void cpumask_copy(struct cpumask *dstp, * cpumask_any - pick a "random" cpu from *srcp * @srcp: the input cpumask * - * Returns >= nr_cpu_ids if no cpus set. + * Return: >= nr_cpu_ids if no cpus set. */ #define cpumask_any(srcp) cpumask_first(srcp) @@ -753,7 +769,7 @@ static inline void cpumask_copy(struct cpumask *dstp, * @mask1: the first input cpumask * @mask2: the second input cpumask * - * Returns >= nr_cpu_ids if no cpus set. + * Return: >= nr_cpu_ids if no cpus set. */ #define cpumask_any_and(mask1, mask2) cpumask_first_and((mask1), (mask2)) @@ -769,7 +785,7 @@ static inline void cpumask_copy(struct cpumask *dstp, * @len: the length of the buffer * @dstp: the cpumask to set. * - * Returns -errno, or 0 for success. + * Return: -errno, or 0 for success. */ static inline int cpumask_parse_user(const char __user *buf, int len, struct cpumask *dstp) @@ -783,7 +799,7 @@ static inline int cpumask_parse_user(const char __user *buf, int len, * @len: the length of the buffer * @dstp: the cpumask to set. * - * Returns -errno, or 0 for success. + * Return: -errno, or 0 for success. */ static inline int cpumask_parselist_user(const char __user *buf, int len, struct cpumask *dstp) @@ -797,7 +813,7 @@ static inline int cpumask_parselist_user(const char __user *buf, int len, * @buf: the buffer to extract from * @dstp: the cpumask to set. * - * Returns -errno, or 0 for success. + * Return: -errno, or 0 for success. */ static inline int cpumask_parse(const char *buf, struct cpumask *dstp) { @@ -809,7 +825,7 @@ static inline int cpumask_parse(const char *buf, struct cpumask *dstp) * @buf: the buffer to extract from * @dstp: the cpumask to set. * - * Returns -errno, or 0 for success. + * Return: -errno, or 0 for success. */ static inline int cpulist_parse(const char *buf, struct cpumask *dstp) { @@ -817,7 +833,9 @@ static inline int cpulist_parse(const char *buf, struct cpumask *dstp) } /** - * cpumask_size - size to allocate for a 'struct cpumask' in bytes + * cpumask_size - calculate size to allocate for a 'struct cpumask' in bytes + * + * Return: size to allocate for a &struct cpumask in bytes */ static inline unsigned int cpumask_size(void) { @@ -831,7 +849,7 @@ static inline unsigned int cpumask_size(void) * little more difficult, we typedef cpumask_var_t to an array or a * pointer: doing &mask on an array is a noop, so it still works. * - * ie. + * i.e. * cpumask_var_t tmpmask; * if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL)) * return -ENOMEM; @@ -887,6 +905,8 @@ bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags, int node) * a nop returning a constant 1 (in ). * * See alloc_cpumask_var_node. + * + * Return: %true if allocation succeeded, %false if not */ static inline bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) @@ -1025,7 +1045,7 @@ set_cpu_dying(unsigned int cpu, bool dying) } /** - * to_cpumask - convert an NR_CPUS bitmap to a struct cpumask * + * to_cpumask - convert a NR_CPUS bitmap to a struct cpumask * * @bitmap: the bitmap * * There are a few places where cpumask_var_t isn't appropriate and @@ -1068,6 +1088,8 @@ static inline const struct cpumask *get_cpu_mask(unsigned int cpu) * interface gives only a momentary snapshot and is not protected against * concurrent CPU hotplug operations unless invoked from a cpuhp_lock held * region. + * + * Return: momentary snapshot of the number of online CPUs */ static __always_inline unsigned int num_online_cpus(void) { @@ -1160,7 +1182,7 @@ static inline bool cpu_dying(unsigned int cpu) * @mask: the cpumask to copy * @buf: the buffer to copy into * - * Returns the length of the (null-terminated) @buf string, zero if + * Return: the length of the (null-terminated) @buf string, zero if * nothing is copied. */ static inline ssize_t @@ -1183,7 +1205,7 @@ cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask) * cpumask; Typically used by bin_attribute to export cpumask bitmask * ABI. * - * Returns the length of how many bytes have been copied, excluding + * Return: the length of how many bytes have been copied, excluding * terminating '\0'. */ static inline ssize_t @@ -1204,6 +1226,9 @@ cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask, * * Everything is same with the above cpumap_print_bitmask_to_buf() * except the print format. + * + * Return: the length of how many bytes have been copied, excluding + * terminating '\0'. */ static inline ssize_t cpumap_print_list_to_buf(char *buf, const struct cpumask *mask, diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index 0f3a656293b0..acc55626afdc 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h @@ -50,6 +50,7 @@ void vmcore_cleanup(void); #define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x)) #endif +#ifndef is_kdump_kernel /* * is_kdump_kernel() checks whether this kernel is booting after a panic of * previous kernel or not. This is determined by checking if previous kernel @@ -64,6 +65,7 @@ static inline bool is_kdump_kernel(void) { return elfcorehdr_addr != ELFCORE_ADDR_MAX; } +#endif /* is_vmcore_usable() checks if the kernel is booting after a panic and * the vmcore region is usable. @@ -75,7 +77,8 @@ static inline bool is_kdump_kernel(void) static inline int is_vmcore_usable(void) { - return is_kdump_kernel() && elfcorehdr_addr != ELFCORE_ADDR_ERR ? 1 : 0; + return elfcorehdr_addr != ELFCORE_ADDR_ERR && + elfcorehdr_addr != ELFCORE_ADDR_MAX ? 1 : 0; } /* vmcore_unusable() marks the vmcore as unusable, @@ -84,8 +87,7 @@ static inline int is_vmcore_usable(void) static inline void vmcore_unusable(void) { - if (is_kdump_kernel()) - elfcorehdr_addr = ELFCORE_ADDR_ERR; + elfcorehdr_addr = ELFCORE_ADDR_ERR; } /** diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h index 515d7fcb9634..5fb1f12c33f9 100644 --- a/include/linux/seq_buf.h +++ b/include/linux/seq_buf.h @@ -14,19 +14,25 @@ * @buffer: pointer to the buffer * @size: size of the buffer * @len: the amount of data inside the buffer - * @readpos: The next position to read in the buffer. */ struct seq_buf { char *buffer; size_t size; size_t len; - loff_t readpos; }; +#define DECLARE_SEQ_BUF(NAME, SIZE) \ + char __ ## NAME ## _buffer[SIZE] = ""; \ + struct seq_buf NAME = { \ + .buffer = &__ ## NAME ## _buffer, \ + .size = SIZE, \ + } + static inline void seq_buf_clear(struct seq_buf *s) { s->len = 0; - s->readpos = 0; + if (s->size) + s->buffer[0] = '\0'; } static inline void @@ -39,7 +45,7 @@ seq_buf_init(struct seq_buf *s, char *buf, unsigned int size) /* * seq_buf have a buffer that might overflow. When this happens - * the len and size are set to be equal. + * len is set to be greater than size. */ static inline bool seq_buf_has_overflowed(struct seq_buf *s) @@ -72,8 +78,8 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) } /** - * seq_buf_terminate - Make sure buffer is nul terminated - * @s: the seq_buf descriptor to terminate. + * seq_buf_str - get %NUL-terminated C string from seq_buf + * @s: the seq_buf handle * * This makes sure that the buffer in @s is nul terminated and * safe to read as a string. @@ -84,16 +90,20 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) * * After this function is called, s->buffer is safe to use * in string operations. + * + * Returns @s->buf after making sure it is terminated. */ -static inline void seq_buf_terminate(struct seq_buf *s) +static inline const char *seq_buf_str(struct seq_buf *s) { if (WARN_ON(s->size == 0)) - return; + return ""; if (seq_buf_buffer_left(s)) s->buffer[s->len] = 0; else s->buffer[s->size - 1] = 0; + + return s->buffer; } /** @@ -143,7 +153,7 @@ extern __printf(2, 0) int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args); extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s); extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, - int cnt); + size_t start, int cnt); extern int seq_buf_puts(struct seq_buf *s, const char *str); extern int seq_buf_putc(struct seq_buf *s, unsigned char c); extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int len); diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 5eb88a66eb68..d68ff9b1247f 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -492,6 +492,7 @@ enum { EVENT_FILE_FL_TRIGGER_COND_BIT, EVENT_FILE_FL_PID_FILTER_BIT, EVENT_FILE_FL_WAS_ENABLED_BIT, + EVENT_FILE_FL_FREED_BIT, }; extern struct trace_event_file *trace_get_event_file(const char *instance, @@ -630,6 +631,7 @@ extern int __kprobe_event_add_fields(struct dynevent_cmd *cmd, ...); * TRIGGER_COND - When set, one or more triggers has an associated filter * PID_FILTER - When set, the event is filtered based on pid * WAS_ENABLED - Set when enabled to know to clear trace on module removal + * FREED - File descriptor is freed, all fields should be considered invalid */ enum { EVENT_FILE_FL_ENABLED = (1 << EVENT_FILE_FL_ENABLED_BIT), @@ -643,13 +645,14 @@ enum { EVENT_FILE_FL_TRIGGER_COND = (1 << EVENT_FILE_FL_TRIGGER_COND_BIT), EVENT_FILE_FL_PID_FILTER = (1 << EVENT_FILE_FL_PID_FILTER_BIT), EVENT_FILE_FL_WAS_ENABLED = (1 << EVENT_FILE_FL_WAS_ENABLED_BIT), + EVENT_FILE_FL_FREED = (1 << EVENT_FILE_FL_FREED_BIT), }; struct trace_event_file { struct list_head list; struct trace_event_call *event_call; struct event_filter __rcu *filter; - struct eventfs_file *ef; + struct eventfs_inode *ei; struct trace_array *tr; struct trace_subsystem_dir *system; struct list_head triggers; @@ -671,6 +674,7 @@ struct trace_event_file { * caching and such. Which is mostly OK ;-) */ unsigned long flags; + atomic_t ref; /* ref count for opened files */ atomic_t sm_ref; /* soft-mode reference counter */ atomic_t tm_ref; /* trigger-mode reference counter */ }; diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h index 6be92bf559fe..3691e0e76a1a 100644 --- a/include/linux/trace_seq.h +++ b/include/linux/trace_seq.h @@ -14,6 +14,7 @@ struct trace_seq { char buffer[PAGE_SIZE]; struct seq_buf seq; + size_t readpos; int full; }; @@ -22,6 +23,7 @@ trace_seq_init(struct trace_seq *s) { seq_buf_init(&s->seq, s->buffer, PAGE_SIZE); s->full = 0; + s->readpos = 0; } /** diff --git a/include/linux/tracefs.h b/include/linux/tracefs.h index 009072792fa3..7a5fe17b6bf9 100644 --- a/include/linux/tracefs.h +++ b/include/linux/tracefs.h @@ -23,26 +23,69 @@ struct file_operations; struct eventfs_file; -struct dentry *eventfs_create_events_dir(const char *name, - struct dentry *parent); +/** + * eventfs_callback - A callback function to create dynamic files in eventfs + * @name: The name of the file that is to be created + * @mode: return the file mode for the file (RW access, etc) + * @data: data to pass to the created file ops + * @fops: the file operations of the created file + * + * The evetnfs files are dynamically created. The struct eventfs_entry array + * is passed to eventfs_create_dir() or eventfs_create_events_dir() that will + * be used to create the files within those directories. When a lookup + * or access to a file within the directory is made, the struct eventfs_entry + * array is used to find a callback() with the matching name that is being + * referenced (for lookups, the entire array is iterated and each callback + * will be called). + * + * The callback will be called with @name for the name of the file to create. + * The callback can return less than 1 to indicate that no file should be + * created. + * + * If a file is to be created, then @mode should be populated with the file + * mode (permissions) for which the file is created for. This would be + * used to set the created inode i_mode field. + * + * The @data should be set to the data passed to the other file operations + * (read, write, etc). Note, @data will also point to the data passed in + * to eventfs_create_dir() or eventfs_create_events_dir(), but the callback + * can replace the data if it chooses to. Otherwise, the original data + * will be used for the file operation functions. + * + * The @fops should be set to the file operations that will be used to create + * the inode. + * + * NB. This callback is called while holding internal locks of the eventfs + * system. The callback must not call any code that might also call into + * the tracefs or eventfs system or it will risk creating a deadlock. + */ +typedef int (*eventfs_callback)(const char *name, umode_t *mode, void **data, + const struct file_operations **fops); -struct eventfs_file *eventfs_add_subsystem_dir(const char *name, - struct dentry *parent); +/** + * struct eventfs_entry - dynamically created eventfs file call back handler + * @name: Then name of the dynamic file in an eventfs directory + * @callback: The callback to get the fops of the file when it is created + * + * See evenfs_callback() typedef for how to set up @callback. + */ +struct eventfs_entry { + const char *name; + eventfs_callback callback; +}; -struct eventfs_file *eventfs_add_dir(const char *name, - struct eventfs_file *ef_parent); +struct eventfs_inode; -int eventfs_add_file(const char *name, umode_t mode, - struct eventfs_file *ef_parent, void *data, - const struct file_operations *fops); +struct eventfs_inode *eventfs_create_events_dir(const char *name, struct dentry *parent, + const struct eventfs_entry *entries, + int size, void *data); -int eventfs_add_events_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); +struct eventfs_inode *eventfs_create_dir(const char *name, struct eventfs_inode *parent, + const struct eventfs_entry *entries, + int size, void *data); -void eventfs_remove(struct eventfs_file *ef); - -void eventfs_remove_events_dir(struct dentry *dentry); +void eventfs_remove_events_dir(struct eventfs_inode *ei); +void eventfs_remove_dir(struct eventfs_inode *ei); struct dentry *tracefs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 81d09ef9aa50..25c8d7677539 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -31,6 +31,12 @@ struct landlock_ruleset_attr { * this access right. */ __u64 handled_access_fs; + /** + * @handled_access_net: Bitmask of actions (cf. `Network flags`_) + * that is handled by this ruleset and should then be forbidden if no + * rule explicitly allow them. + */ + __u64 handled_access_net; }; /* @@ -54,6 +60,11 @@ enum landlock_rule_type { * landlock_path_beneath_attr . */ LANDLOCK_RULE_PATH_BENEATH = 1, + /** + * @LANDLOCK_RULE_NET_PORT: Type of a &struct + * landlock_net_port_attr . + */ + LANDLOCK_RULE_NET_PORT, }; /** @@ -79,6 +90,31 @@ struct landlock_path_beneath_attr { */ } __attribute__((packed)); +/** + * struct landlock_net_port_attr - Network port definition + * + * Argument of sys_landlock_add_rule(). + */ +struct landlock_net_port_attr { + /** + * @allowed_access: Bitmask of allowed access network for a port + * (cf. `Network flags`_). + */ + __u64 allowed_access; + /** + * @port: Network port in host endianness. + * + * It should be noted that port 0 passed to :manpage:`bind(2)` will + * bind to an available port from a specific port range. This can be + * configured thanks to the ``/proc/sys/net/ipv4/ip_local_port_range`` + * sysctl (also used for IPv6). A Landlock rule with port 0 and the + * ``LANDLOCK_ACCESS_NET_BIND_TCP`` right means that requesting to bind + * on port 0 is allowed and it will automatically translate to binding + * on the related port range. + */ + __u64 port; +}; + /** * DOC: fs_access * @@ -189,4 +225,23 @@ struct landlock_path_beneath_attr { #define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14) /* clang-format on */ +/** + * DOC: net_access + * + * Network flags + * ~~~~~~~~~~~~~~~~ + * + * These flags enable to restrict a sandboxed process to a set of network + * actions. This is supported since the Landlock ABI version 4. + * + * TCP sockets with allowed actions: + * + * - %LANDLOCK_ACCESS_NET_BIND_TCP: Bind a TCP socket to a local port. + * - %LANDLOCK_ACCESS_NET_CONNECT_TCP: Connect an active TCP socket to + * a remote port. + */ +/* clang-format off */ +#define LANDLOCK_ACCESS_NET_BIND_TCP (1ULL << 0) +#define LANDLOCK_ACCESS_NET_CONNECT_TCP (1ULL << 1) +/* clang-format on */ #endif /* _UAPI_LINUX_LANDLOCK_H */ diff --git a/include/uapi/linux/user_events.h b/include/uapi/linux/user_events.h index 2984aae4a2b4..f74f3aedd49c 100644 --- a/include/uapi/linux/user_events.h +++ b/include/uapi/linux/user_events.h @@ -17,6 +17,15 @@ /* Create dynamic location entry within a 32-bit value */ #define DYN_LOC(offset, size) ((size) << 16 | (offset)) +/* List of supported registration flags */ +enum user_reg_flag { + /* Event will not delete upon last reference closing */ + USER_EVENT_REG_PERSIST = 1U << 0, + + /* This value or above is currently non-ABI */ + USER_EVENT_REG_MAX = 1U << 1, +}; + /* * Describes an event registration and stores the results of the registration. * This structure is passed to the DIAG_IOCSREG ioctl, callers at a minimum @@ -33,7 +42,7 @@ struct user_reg { /* Input: Enable size in bytes at address */ __u8 enable_size; - /* Input: Flags for future use, set to 0 */ + /* Input: Flags to use, if any */ __u16 flags; /* Input: Address to update when enabled */ diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 61328328c474..ecbc9b6aba3a 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -243,7 +243,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, * symbols are exported and normal relas can be used instead. */ if (!sec_vmlinux && sym_vmlinux) { - pr_err("invalid access to vmlinux symbol '%s' from module-specific livepatch relocation section", + pr_err("invalid access to vmlinux symbol '%s' from module-specific livepatch relocation section\n", sym_name); return -EINVAL; } diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile index f5b388e810b9..39a2b61c7232 100644 --- a/kernel/printk/Makefile +++ b/kernel/printk/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y = printk.o -obj-$(CONFIG_PRINTK) += printk_safe.o +obj-$(CONFIG_PRINTK) += printk_safe.o nbcon.o obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o obj-$(CONFIG_PRINTK_INDEX) += index.o diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index 7d4979d5c3ce..6c2afee5ef62 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -3,6 +3,8 @@ * internal.h - printk internal definitions */ #include +#include +#include "printk_ringbuffer.h" #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL) void __init printk_sysctl_init(void); @@ -12,6 +14,12 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, #define printk_sysctl_init() do { } while (0) #endif +#define con_printk(lvl, con, fmt, ...) \ + printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \ + (con->flags & CON_NBCON) ? "" : "legacy ", \ + (con->flags & CON_BOOT) ? "boot" : "", \ + con->name, con->index, ##__VA_ARGS__) + #ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK_CALLER @@ -35,6 +43,8 @@ enum printk_info_flags { LOG_CONT = 8, /* text is a fragment of a continuation line */ }; +extern struct printk_ringbuffer *prb; + __printf(4, 0) int vprintk_store(int facility, int level, const struct dev_printk_info *dev_info, @@ -61,6 +71,13 @@ void defer_console_output(void); u16 printk_parse_prefix(const char *text, int *level, enum printk_info_flags *flags); + +u64 nbcon_seq_read(struct console *con); +void nbcon_seq_force(struct console *con, u64 seq); +bool nbcon_alloc(struct console *con); +void nbcon_init(struct console *con); +void nbcon_free(struct console *con); + #else #define PRINTK_PREFIX_MAX 0 @@ -76,8 +93,16 @@ u16 printk_parse_prefix(const char *text, int *level, #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags) static inline bool printk_percpu_data_ready(void) { return false; } +static inline u64 nbcon_seq_read(struct console *con) { return 0; } +static inline void nbcon_seq_force(struct console *con, u64 seq) { } +static inline bool nbcon_alloc(struct console *con) { return false; } +static inline void nbcon_init(struct console *con) { } +static inline void nbcon_free(struct console *con) { } + #endif /* CONFIG_PRINTK */ +extern struct printk_buffers printk_shared_pbufs; + /** * struct printk_buffers - Buffers to read/format/output printk messages. * @outbuf: After formatting, contains text to output. @@ -105,3 +130,9 @@ struct printk_message { }; bool other_cpu_in_panic(void); +bool printk_get_next_message(struct printk_message *pmsg, u64 seq, + bool is_extended, bool may_supress); + +#ifdef CONFIG_PRINTK +void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped); +#endif diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c new file mode 100644 index 000000000000..b96077152f49 --- /dev/null +++ b/kernel/printk/nbcon.c @@ -0,0 +1,1029 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2022 Linutronix GmbH, John Ogness +// Copyright (C) 2022 Intel, Thomas Gleixner + +#include +#include +#include +#include +#include "internal.h" +/* + * Printk console printing implementation for consoles which does not depend + * on the legacy style console_lock mechanism. + * + * The state of the console is maintained in the "nbcon_state" atomic + * variable. + * + * The console is locked when: + * + * - The 'prio' field contains the priority of the context that owns the + * console. Only higher priority contexts are allowed to take over the + * lock. A value of 0 (NBCON_PRIO_NONE) means the console is not locked. + * + * - The 'cpu' field denotes on which CPU the console is locked. It is used + * to prevent busy waiting on the same CPU. Also it informs the lock owner + * that it has lost the lock in a more complex scenario when the lock was + * taken over by a higher priority context, released, and taken on another + * CPU with the same priority as the interrupted owner. + * + * The acquire mechanism uses a few more fields: + * + * - The 'req_prio' field is used by the handover approach to make the + * current owner aware that there is a context with a higher priority + * waiting for the friendly handover. + * + * - The 'unsafe' field allows to take over the console in a safe way in the + * middle of emitting a message. The field is set only when accessing some + * shared resources or when the console device is manipulated. It can be + * cleared, for example, after emitting one character when the console + * device is in a consistent state. + * + * - The 'unsafe_takeover' field is set when a hostile takeover took the + * console in an unsafe state. The console will stay in the unsafe state + * until re-initialized. + * + * The acquire mechanism uses three approaches: + * + * 1) Direct acquire when the console is not owned or is owned by a lower + * priority context and is in a safe state. + * + * 2) Friendly handover mechanism uses a request/grant handshake. It is used + * when the current owner has lower priority and the console is in an + * unsafe state. + * + * The requesting context: + * + * a) Sets its priority into the 'req_prio' field. + * + * b) Waits (with a timeout) for the owning context to unlock the + * console. + * + * c) Takes the lock and clears the 'req_prio' field. + * + * The owning context: + * + * a) Observes the 'req_prio' field set on exit from the unsafe + * console state. + * + * b) Gives up console ownership by clearing the 'prio' field. + * + * 3) Unsafe hostile takeover allows to take over the lock even when the + * console is an unsafe state. It is used only in panic() by the final + * attempt to flush consoles in a try and hope mode. + * + * Note that separate record buffers are used in panic(). As a result, + * the messages can be read and formatted without any risk even after + * using the hostile takeover in unsafe state. + * + * The release function simply clears the 'prio' field. + * + * All operations on @console::nbcon_state are atomic cmpxchg based to + * handle concurrency. + * + * The acquire/release functions implement only minimal policies: + * + * - Preference for higher priority contexts. + * - Protection of the panic CPU. + * + * All other policy decisions must be made at the call sites: + * + * - What is marked as an unsafe section. + * - Whether to spin-wait if there is already an owner and the console is + * in an unsafe state. + * - Whether to attempt an unsafe hostile takeover. + * + * The design allows to implement the well known: + * + * acquire() + * output_one_printk_record() + * release() + * + * The output of one printk record might be interrupted with a higher priority + * context. The new owner is supposed to reprint the entire interrupted record + * from scratch. + */ + +/** + * nbcon_state_set - Helper function to set the console state + * @con: Console to update + * @new: The new state to write + * + * Only to be used when the console is not yet or no longer visible in the + * system. Otherwise use nbcon_state_try_cmpxchg(). + */ +static inline void nbcon_state_set(struct console *con, struct nbcon_state *new) +{ + atomic_set(&ACCESS_PRIVATE(con, nbcon_state), new->atom); +} + +/** + * nbcon_state_read - Helper function to read the console state + * @con: Console to read + * @state: The state to store the result + */ +static inline void nbcon_state_read(struct console *con, struct nbcon_state *state) +{ + state->atom = atomic_read(&ACCESS_PRIVATE(con, nbcon_state)); +} + +/** + * nbcon_state_try_cmpxchg() - Helper function for atomic_try_cmpxchg() on console state + * @con: Console to update + * @cur: Old/expected state + * @new: New state + * + * Return: True on success. False on fail and @cur is updated. + */ +static inline bool nbcon_state_try_cmpxchg(struct console *con, struct nbcon_state *cur, + struct nbcon_state *new) +{ + return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom); +} + +#ifdef CONFIG_64BIT + +#define __seq_to_nbcon_seq(seq) (seq) +#define __nbcon_seq_to_seq(seq) (seq) + +#else /* CONFIG_64BIT */ + +#define __seq_to_nbcon_seq(seq) ((u32)seq) + +static inline u64 __nbcon_seq_to_seq(u32 nbcon_seq) +{ + u64 seq; + u64 rb_next_seq; + + /* + * The provided sequence is only the lower 32 bits of the ringbuffer + * sequence. It needs to be expanded to 64bit. Get the next sequence + * number from the ringbuffer and fold it. + * + * Having a 32bit representation in the console is sufficient. + * If a console ever gets more than 2^31 records behind + * the ringbuffer then this is the least of the problems. + * + * Also the access to the ring buffer is always safe. + */ + rb_next_seq = prb_next_seq(prb); + seq = rb_next_seq - ((u32)rb_next_seq - nbcon_seq); + + return seq; +} + +#endif /* CONFIG_64BIT */ + +/** + * nbcon_seq_read - Read the current console sequence + * @con: Console to read the sequence of + * + * Return: Sequence number of the next record to print on @con. + */ +u64 nbcon_seq_read(struct console *con) +{ + unsigned long nbcon_seq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_seq)); + + return __nbcon_seq_to_seq(nbcon_seq); +} + +/** + * nbcon_seq_force - Force console sequence to a specific value + * @con: Console to work on + * @seq: Sequence number value to set + * + * Only to be used during init (before registration) or in extreme situations + * (such as panic with CONSOLE_REPLAY_ALL). + */ +void nbcon_seq_force(struct console *con, u64 seq) +{ + /* + * If the specified record no longer exists, the oldest available record + * is chosen. This is especially important on 32bit systems because only + * the lower 32 bits of the sequence number are stored. The upper 32 bits + * are derived from the sequence numbers available in the ringbuffer. + */ + u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb)); + + atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __seq_to_nbcon_seq(valid_seq)); + + /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */ + con->seq = 0; +} + +/** + * nbcon_seq_try_update - Try to update the console sequence number + * @ctxt: Pointer to an acquire context that contains + * all information about the acquire mode + * @new_seq: The new sequence number to set + * + * @ctxt->seq is updated to the new value of @con::nbcon_seq (expanded to + * the 64bit value). This could be a different value than @new_seq if + * nbcon_seq_force() was used or the current context no longer owns the + * console. In the later case, it will stop printing anyway. + */ +static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq) +{ + unsigned long nbcon_seq = __seq_to_nbcon_seq(ctxt->seq); + struct console *con = ctxt->console; + + if (atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_seq), &nbcon_seq, + __seq_to_nbcon_seq(new_seq))) { + ctxt->seq = new_seq; + } else { + ctxt->seq = nbcon_seq_read(con); + } +} + +/** + * nbcon_context_try_acquire_direct - Try to acquire directly + * @ctxt: The context of the caller + * @cur: The current console state + * + * Acquire the console when it is released. Also acquire the console when + * the current owner has a lower priority and the console is in a safe state. + * + * Return: 0 on success. Otherwise, an error code on failure. Also @cur + * is updated to the latest state when failed to modify it. + * + * Errors: + * + * -EPERM: A panic is in progress and this is not the panic CPU. + * Or the current owner or waiter has the same or higher + * priority. No acquire method can be successful in + * this case. + * + * -EBUSY: The current owner has a lower priority but the console + * in an unsafe state. The caller should try using + * the handover acquire method. + */ +static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt, + struct nbcon_state *cur) +{ + unsigned int cpu = smp_processor_id(); + struct console *con = ctxt->console; + struct nbcon_state new; + + do { + if (other_cpu_in_panic()) + return -EPERM; + + if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio) + return -EPERM; + + if (cur->unsafe) + return -EBUSY; + + /* + * The console should never be safe for a direct acquire + * if an unsafe hostile takeover has ever happened. + */ + WARN_ON_ONCE(cur->unsafe_takeover); + + new.atom = cur->atom; + new.prio = ctxt->prio; + new.req_prio = NBCON_PRIO_NONE; + new.unsafe = cur->unsafe_takeover; + new.cpu = cpu; + + } while (!nbcon_state_try_cmpxchg(con, cur, &new)); + + return 0; +} + +static bool nbcon_waiter_matches(struct nbcon_state *cur, int expected_prio) +{ + /* + * The request context is well defined by the @req_prio because: + * + * - Only a context with a higher priority can take over the request. + * - There are only three priorities. + * - Only one CPU is allowed to request PANIC priority. + * - Lower priorities are ignored during panic() until reboot. + * + * As a result, the following scenario is *not* possible: + * + * 1. Another context with a higher priority directly takes ownership. + * 2. The higher priority context releases the ownership. + * 3. A lower priority context takes the ownership. + * 4. Another context with the same priority as this context + * creates a request and starts waiting. + */ + + return (cur->req_prio == expected_prio); +} + +/** + * nbcon_context_try_acquire_requested - Try to acquire after having + * requested a handover + * @ctxt: The context of the caller + * @cur: The current console state + * + * This is a helper function for nbcon_context_try_acquire_handover(). + * It is called when the console is in an unsafe state. The current + * owner will release the console on exit from the unsafe region. + * + * Return: 0 on success and @cur is updated to the new console state. + * Otherwise an error code on failure. + * + * Errors: + * + * -EPERM: A panic is in progress and this is not the panic CPU + * or this context is no longer the waiter. + * + * -EBUSY: The console is still locked. The caller should + * continue waiting. + * + * Note: The caller must still remove the request when an error has occurred + * except when this context is no longer the waiter. + */ +static int nbcon_context_try_acquire_requested(struct nbcon_context *ctxt, + struct nbcon_state *cur) +{ + unsigned int cpu = smp_processor_id(); + struct console *con = ctxt->console; + struct nbcon_state new; + + /* Note that the caller must still remove the request! */ + if (other_cpu_in_panic()) + return -EPERM; + + /* + * Note that the waiter will also change if there was an unsafe + * hostile takeover. + */ + if (!nbcon_waiter_matches(cur, ctxt->prio)) + return -EPERM; + + /* If still locked, caller should continue waiting. */ + if (cur->prio != NBCON_PRIO_NONE) + return -EBUSY; + + /* + * The previous owner should have never released ownership + * in an unsafe region. + */ + WARN_ON_ONCE(cur->unsafe); + + new.atom = cur->atom; + new.prio = ctxt->prio; + new.req_prio = NBCON_PRIO_NONE; + new.unsafe = cur->unsafe_takeover; + new.cpu = cpu; + + if (!nbcon_state_try_cmpxchg(con, cur, &new)) { + /* + * The acquire could fail only when it has been taken + * over by a higher priority context. + */ + WARN_ON_ONCE(nbcon_waiter_matches(cur, ctxt->prio)); + return -EPERM; + } + + /* Handover success. This context now owns the console. */ + return 0; +} + +/** + * nbcon_context_try_acquire_handover - Try to acquire via handover + * @ctxt: The context of the caller + * @cur: The current console state + * + * The function must be called only when the context has higher priority + * than the current owner and the console is in an unsafe state. + * It is the case when nbcon_context_try_acquire_direct() returns -EBUSY. + * + * The function sets "req_prio" field to make the current owner aware of + * the request. Then it waits until the current owner releases the console, + * or an even higher context takes over the request, or timeout expires. + * + * The current owner checks the "req_prio" field on exit from the unsafe + * region and releases the console. It does not touch the "req_prio" field + * so that the console stays reserved for the waiter. + * + * Return: 0 on success. Otherwise, an error code on failure. Also @cur + * is updated to the latest state when failed to modify it. + * + * Errors: + * + * -EPERM: A panic is in progress and this is not the panic CPU. + * Or a higher priority context has taken over the + * console or the handover request. + * + * -EBUSY: The current owner is on the same CPU so that the hand + * shake could not work. Or the current owner is not + * willing to wait (zero timeout). Or the console does + * not enter the safe state before timeout passed. The + * caller might still use the unsafe hostile takeover + * when allowed. + * + * -EAGAIN: @cur has changed when creating the handover request. + * The caller should retry with direct acquire. + */ +static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt, + struct nbcon_state *cur) +{ + unsigned int cpu = smp_processor_id(); + struct console *con = ctxt->console; + struct nbcon_state new; + int timeout; + int request_err = -EBUSY; + + /* + * Check that the handover is called when the direct acquire failed + * with -EBUSY. + */ + WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio); + WARN_ON_ONCE(!cur->unsafe); + + /* Handover is not possible on the same CPU. */ + if (cur->cpu == cpu) + return -EBUSY; + + /* + * Console stays unsafe after an unsafe takeover until re-initialized. + * Waiting is not going to help in this case. + */ + if (cur->unsafe_takeover) + return -EBUSY; + + /* Is the caller willing to wait? */ + if (ctxt->spinwait_max_us == 0) + return -EBUSY; + + /* + * Setup a request for the handover. The caller should try to acquire + * the console directly when the current state has been modified. + */ + new.atom = cur->atom; + new.req_prio = ctxt->prio; + if (!nbcon_state_try_cmpxchg(con, cur, &new)) + return -EAGAIN; + + cur->atom = new.atom; + + /* Wait until there is no owner and then acquire the console. */ + for (timeout = ctxt->spinwait_max_us; timeout >= 0; timeout--) { + /* On successful acquire, this request is cleared. */ + request_err = nbcon_context_try_acquire_requested(ctxt, cur); + if (!request_err) + return 0; + + /* + * If the acquire should be aborted, it must be ensured + * that the request is removed before returning to caller. + */ + if (request_err == -EPERM) + break; + + udelay(1); + + /* Re-read the state because some time has passed. */ + nbcon_state_read(con, cur); + } + + /* Timed out or aborted. Carefully remove handover request. */ + do { + /* + * No need to remove request if there is a new waiter. This + * can only happen if a higher priority context has taken over + * the console or the handover request. + */ + if (!nbcon_waiter_matches(cur, ctxt->prio)) + return -EPERM; + + /* Unset request for handover. */ + new.atom = cur->atom; + new.req_prio = NBCON_PRIO_NONE; + if (nbcon_state_try_cmpxchg(con, cur, &new)) { + /* + * Request successfully unset. Report failure of + * acquiring via handover. + */ + cur->atom = new.atom; + return request_err; + } + + /* + * Unable to remove request. Try to acquire in case + * the owner has released the lock. + */ + } while (nbcon_context_try_acquire_requested(ctxt, cur)); + + /* Lucky timing. The acquire succeeded while removing the request. */ + return 0; +} + +/** + * nbcon_context_try_acquire_hostile - Acquire via unsafe hostile takeover + * @ctxt: The context of the caller + * @cur: The current console state + * + * Acquire the console even in the unsafe state. + * + * It can be permitted by setting the 'allow_unsafe_takeover' field only + * by the final attempt to flush messages in panic(). + * + * Return: 0 on success. -EPERM when not allowed by the context. + */ +static int nbcon_context_try_acquire_hostile(struct nbcon_context *ctxt, + struct nbcon_state *cur) +{ + unsigned int cpu = smp_processor_id(); + struct console *con = ctxt->console; + struct nbcon_state new; + + if (!ctxt->allow_unsafe_takeover) + return -EPERM; + + /* Ensure caller is allowed to perform unsafe hostile takeovers. */ + if (WARN_ON_ONCE(ctxt->prio != NBCON_PRIO_PANIC)) + return -EPERM; + + /* + * Check that try_acquire_direct() and try_acquire_handover() returned + * -EBUSY in the right situation. + */ + WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio); + WARN_ON_ONCE(cur->unsafe != true); + + do { + new.atom = cur->atom; + new.cpu = cpu; + new.prio = ctxt->prio; + new.unsafe |= cur->unsafe_takeover; + new.unsafe_takeover |= cur->unsafe; + + } while (!nbcon_state_try_cmpxchg(con, cur, &new)); + + return 0; +} + +static struct printk_buffers panic_nbcon_pbufs; + +/** + * nbcon_context_try_acquire - Try to acquire nbcon console + * @ctxt: The context of the caller + * + * Return: True if the console was acquired. False otherwise. + * + * If the caller allowed an unsafe hostile takeover, on success the + * caller should check the current console state to see if it is + * in an unsafe state. Otherwise, on success the caller may assume + * the console is not in an unsafe state. + */ +__maybe_unused +static bool nbcon_context_try_acquire(struct nbcon_context *ctxt) +{ + unsigned int cpu = smp_processor_id(); + struct console *con = ctxt->console; + struct nbcon_state cur; + int err; + + nbcon_state_read(con, &cur); +try_again: + err = nbcon_context_try_acquire_direct(ctxt, &cur); + if (err != -EBUSY) + goto out; + + err = nbcon_context_try_acquire_handover(ctxt, &cur); + if (err == -EAGAIN) + goto try_again; + if (err != -EBUSY) + goto out; + + err = nbcon_context_try_acquire_hostile(ctxt, &cur); +out: + if (err) + return false; + + /* Acquire succeeded. */ + + /* Assign the appropriate buffer for this context. */ + if (atomic_read(&panic_cpu) == cpu) + ctxt->pbufs = &panic_nbcon_pbufs; + else + ctxt->pbufs = con->pbufs; + + /* Set the record sequence for this context to print. */ + ctxt->seq = nbcon_seq_read(ctxt->console); + + return true; +} + +static bool nbcon_owner_matches(struct nbcon_state *cur, int expected_cpu, + int expected_prio) +{ + /* + * Since consoles can only be acquired by higher priorities, + * owning contexts are uniquely identified by @prio. However, + * since contexts can unexpectedly lose ownership, it is + * possible that later another owner appears with the same + * priority. For this reason @cpu is also needed. + */ + + if (cur->prio != expected_prio) + return false; + + if (cur->cpu != expected_cpu) + return false; + + return true; +} + +/** + * nbcon_context_release - Release the console + * @ctxt: The nbcon context from nbcon_context_try_acquire() + */ +static void nbcon_context_release(struct nbcon_context *ctxt) +{ + unsigned int cpu = smp_processor_id(); + struct console *con = ctxt->console; + struct nbcon_state cur; + struct nbcon_state new; + + nbcon_state_read(con, &cur); + + do { + if (!nbcon_owner_matches(&cur, cpu, ctxt->prio)) + break; + + new.atom = cur.atom; + new.prio = NBCON_PRIO_NONE; + + /* + * If @unsafe_takeover is set, it is kept set so that + * the state remains permanently unsafe. + */ + new.unsafe |= cur.unsafe_takeover; + + } while (!nbcon_state_try_cmpxchg(con, &cur, &new)); + + ctxt->pbufs = NULL; +} + +/** + * nbcon_context_can_proceed - Check whether ownership can proceed + * @ctxt: The nbcon context from nbcon_context_try_acquire() + * @cur: The current console state + * + * Return: True if this context still owns the console. False if + * ownership was handed over or taken. + * + * Must be invoked when entering the unsafe state to make sure that it still + * owns the lock. Also must be invoked when exiting the unsafe context + * to eventually free the lock for a higher priority context which asked + * for the friendly handover. + * + * It can be called inside an unsafe section when the console is just + * temporary in safe state instead of exiting and entering the unsafe + * state. + * + * Also it can be called in the safe context before doing an expensive + * safe operation. It does not make sense to do the operation when + * a higher priority context took the lock. + * + * When this function returns false then the calling context no longer owns + * the console and is no longer allowed to go forward. In this case it must + * back out immediately and carefully. The buffer content is also no longer + * trusted since it no longer belongs to the calling context. + */ +static bool nbcon_context_can_proceed(struct nbcon_context *ctxt, struct nbcon_state *cur) +{ + unsigned int cpu = smp_processor_id(); + + /* Make sure this context still owns the console. */ + if (!nbcon_owner_matches(cur, cpu, ctxt->prio)) + return false; + + /* The console owner can proceed if there is no waiter. */ + if (cur->req_prio == NBCON_PRIO_NONE) + return true; + + /* + * A console owner within an unsafe region is always allowed to + * proceed, even if there are waiters. It can perform a handover + * when exiting the unsafe region. Otherwise the waiter will + * need to perform an unsafe hostile takeover. + */ + if (cur->unsafe) + return true; + + /* Waiters always have higher priorities than owners. */ + WARN_ON_ONCE(cur->req_prio <= cur->prio); + + /* + * Having a safe point for take over and eventually a few + * duplicated characters or a full line is way better than a + * hostile takeover. Post processing can take care of the garbage. + * Release and hand over. + */ + nbcon_context_release(ctxt); + + /* + * It is not clear whether the waiter really took over ownership. The + * outermost callsite must make the final decision whether console + * ownership is needed for it to proceed. If yes, it must reacquire + * ownership (possibly hostile) before carefully proceeding. + * + * The calling context no longer owns the console so go back all the + * way instead of trying to implement reacquire heuristics in tons of + * places. + */ + return false; +} + +/** + * nbcon_can_proceed - Check whether ownership can proceed + * @wctxt: The write context that was handed to the write function + * + * Return: True if this context still owns the console. False if + * ownership was handed over or taken. + * + * It is used in nbcon_enter_unsafe() to make sure that it still owns the + * lock. Also it is used in nbcon_exit_unsafe() to eventually free the lock + * for a higher priority context which asked for the friendly handover. + * + * It can be called inside an unsafe section when the console is just + * temporary in safe state instead of exiting and entering the unsafe state. + * + * Also it can be called in the safe context before doing an expensive safe + * operation. It does not make sense to do the operation when a higher + * priority context took the lock. + * + * When this function returns false then the calling context no longer owns + * the console and is no longer allowed to go forward. In this case it must + * back out immediately and carefully. The buffer content is also no longer + * trusted since it no longer belongs to the calling context. + */ +bool nbcon_can_proceed(struct nbcon_write_context *wctxt) +{ + struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); + struct console *con = ctxt->console; + struct nbcon_state cur; + + nbcon_state_read(con, &cur); + + return nbcon_context_can_proceed(ctxt, &cur); +} +EXPORT_SYMBOL_GPL(nbcon_can_proceed); + +#define nbcon_context_enter_unsafe(c) __nbcon_context_update_unsafe(c, true) +#define nbcon_context_exit_unsafe(c) __nbcon_context_update_unsafe(c, false) + +/** + * __nbcon_context_update_unsafe - Update the unsafe bit in @con->nbcon_state + * @ctxt: The nbcon context from nbcon_context_try_acquire() + * @unsafe: The new value for the unsafe bit + * + * Return: True if the unsafe state was updated and this context still + * owns the console. Otherwise false if ownership was handed + * over or taken. + * + * This function allows console owners to modify the unsafe status of the + * console. + * + * When this function returns false then the calling context no longer owns + * the console and is no longer allowed to go forward. In this case it must + * back out immediately and carefully. The buffer content is also no longer + * trusted since it no longer belongs to the calling context. + * + * Internal helper to avoid duplicated code. + */ +static bool __nbcon_context_update_unsafe(struct nbcon_context *ctxt, bool unsafe) +{ + struct console *con = ctxt->console; + struct nbcon_state cur; + struct nbcon_state new; + + nbcon_state_read(con, &cur); + + do { + /* + * The unsafe bit must not be cleared if an + * unsafe hostile takeover has occurred. + */ + if (!unsafe && cur.unsafe_takeover) + goto out; + + if (!nbcon_context_can_proceed(ctxt, &cur)) + return false; + + new.atom = cur.atom; + new.unsafe = unsafe; + } while (!nbcon_state_try_cmpxchg(con, &cur, &new)); + + cur.atom = new.atom; +out: + return nbcon_context_can_proceed(ctxt, &cur); +} + +/** + * nbcon_enter_unsafe - Enter an unsafe region in the driver + * @wctxt: The write context that was handed to the write function + * + * Return: True if this context still owns the console. False if + * ownership was handed over or taken. + * + * When this function returns false then the calling context no longer owns + * the console and is no longer allowed to go forward. In this case it must + * back out immediately and carefully. The buffer content is also no longer + * trusted since it no longer belongs to the calling context. + */ +bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) +{ + struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); + + return nbcon_context_enter_unsafe(ctxt); +} +EXPORT_SYMBOL_GPL(nbcon_enter_unsafe); + +/** + * nbcon_exit_unsafe - Exit an unsafe region in the driver + * @wctxt: The write context that was handed to the write function + * + * Return: True if this context still owns the console. False if + * ownership was handed over or taken. + * + * When this function returns false then the calling context no longer owns + * the console and is no longer allowed to go forward. In this case it must + * back out immediately and carefully. The buffer content is also no longer + * trusted since it no longer belongs to the calling context. + */ +bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) +{ + struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); + + return nbcon_context_exit_unsafe(ctxt); +} +EXPORT_SYMBOL_GPL(nbcon_exit_unsafe); + +/** + * nbcon_emit_next_record - Emit a record in the acquired context + * @wctxt: The write context that will be handed to the write function + * + * Return: True if this context still owns the console. False if + * ownership was handed over or taken. + * + * When this function returns false then the calling context no longer owns + * the console and is no longer allowed to go forward. In this case it must + * back out immediately and carefully. The buffer content is also no longer + * trusted since it no longer belongs to the calling context. If the caller + * wants to do more it must reacquire the console first. + * + * When true is returned, @wctxt->ctxt.backlog indicates whether there are + * still records pending in the ringbuffer, + */ +__maybe_unused +static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) +{ + struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); + struct console *con = ctxt->console; + bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; + struct printk_message pmsg = { + .pbufs = ctxt->pbufs, + }; + unsigned long con_dropped; + struct nbcon_state cur; + unsigned long dropped; + bool done; + + /* + * The printk buffers are filled within an unsafe section. This + * prevents NBCON_PRIO_NORMAL and NBCON_PRIO_EMERGENCY from + * clobbering each other. + */ + + if (!nbcon_context_enter_unsafe(ctxt)) + return false; + + ctxt->backlog = printk_get_next_message(&pmsg, ctxt->seq, is_extended, true); + if (!ctxt->backlog) + return nbcon_context_exit_unsafe(ctxt); + + /* + * @con->dropped is not protected in case of an unsafe hostile + * takeover. In that situation the update can be racy so + * annotate it accordingly. + */ + con_dropped = data_race(READ_ONCE(con->dropped)); + + dropped = con_dropped + pmsg.dropped; + if (dropped && !is_extended) + console_prepend_dropped(&pmsg, dropped); + + if (!nbcon_context_exit_unsafe(ctxt)) + return false; + + /* For skipped records just update seq/dropped in @con. */ + if (pmsg.outbuf_len == 0) + goto update_con; + + /* Initialize the write context for driver callbacks. */ + wctxt->outbuf = &pmsg.pbufs->outbuf[0]; + wctxt->len = pmsg.outbuf_len; + nbcon_state_read(con, &cur); + wctxt->unsafe_takeover = cur.unsafe_takeover; + + if (con->write_atomic) { + done = con->write_atomic(con, wctxt); + } else { + nbcon_context_release(ctxt); + WARN_ON_ONCE(1); + done = false; + } + + /* If not done, the emit was aborted. */ + if (!done) + return false; + + /* + * Since any dropped message was successfully output, reset the + * dropped count for the console. + */ + dropped = 0; +update_con: + /* + * The dropped count and the sequence number are updated within an + * unsafe section. This limits update races to the panic context and + * allows the panic context to win. + */ + + if (!nbcon_context_enter_unsafe(ctxt)) + return false; + + if (dropped != con_dropped) { + /* Counterpart to the READ_ONCE() above. */ + WRITE_ONCE(con->dropped, dropped); + } + + nbcon_seq_try_update(ctxt, pmsg.seq + 1); + + return nbcon_context_exit_unsafe(ctxt); +} + +/** + * nbcon_alloc - Allocate buffers needed by the nbcon console + * @con: Console to allocate buffers for + * + * Return: True on success. False otherwise and the console cannot + * be used. + * + * This is not part of nbcon_init() because buffer allocation must + * be performed earlier in the console registration process. + */ +bool nbcon_alloc(struct console *con) +{ + if (con->flags & CON_BOOT) { + /* + * Boot console printing is synchronized with legacy console + * printing, so boot consoles can share the same global printk + * buffers. + */ + con->pbufs = &printk_shared_pbufs; + } else { + con->pbufs = kmalloc(sizeof(*con->pbufs), GFP_KERNEL); + if (!con->pbufs) { + con_printk(KERN_ERR, con, "failed to allocate printing buffer\n"); + return false; + } + } + + return true; +} + +/** + * nbcon_init - Initialize the nbcon console specific data + * @con: Console to initialize + * + * nbcon_alloc() *must* be called and succeed before this function + * is called. + * + * This function expects that the legacy @con->seq has been set. + */ +void nbcon_init(struct console *con) +{ + struct nbcon_state state = { }; + + /* nbcon_alloc() must have been called and successful! */ + BUG_ON(!con->pbufs); + + nbcon_seq_force(con, con->seq); + nbcon_state_set(con, &state); +} + +/** + * nbcon_free - Free and cleanup the nbcon console specific data + * @con: Console to free/cleanup nbcon data + */ +void nbcon_free(struct console *con) +{ + struct nbcon_state state = { }; + + nbcon_state_set(con, &state); + + /* Boot consoles share global printk buffers. */ + if (!(con->flags & CON_BOOT)) + kfree(con->pbufs); + + con->pbufs = NULL; +} diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 374715b66ef2..e50ec9362da9 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -104,12 +104,6 @@ DEFINE_STATIC_SRCU(console_srcu); */ int __read_mostly suppress_printk; -/* - * During panic, heavy printk by other CPUs can delay the - * panic and risk deadlock on console resources. - */ -static int __read_mostly suppress_panic_printk; - #ifdef CONFIG_LOCKDEP static struct lockdep_map console_lock_dep_map = { .name = "console_lock" @@ -447,6 +441,12 @@ static int console_msg_format = MSG_FORMAT_DEFAULT; static DEFINE_MUTEX(syslog_lock); #ifdef CONFIG_PRINTK +/* + * During panic, heavy printk by other CPUs can delay the + * panic and risk deadlock on console resources. + */ +static int __read_mostly suppress_panic_printk; + DECLARE_WAIT_QUEUE_HEAD(log_wait); /* All 3 protected by @syslog_lock. */ /* the next printk record to read by syslog(READ) or /proc/kmsg */ @@ -496,7 +496,7 @@ _DEFINE_PRINTKRB(printk_rb_static, CONFIG_LOG_BUF_SHIFT - PRB_AVGBITS, static struct printk_ringbuffer printk_rb_dynamic; -static struct printk_ringbuffer *prb = &printk_rb_static; +struct printk_ringbuffer *prb = &printk_rb_static; /* * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before @@ -700,9 +700,6 @@ out: return len; } -static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, - bool is_extended, bool may_supress); - /* /dev/kmsg - userspace message inject/listen interface */ struct devkmsg_user { atomic64_t seq; @@ -1671,7 +1668,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) prb_rec_init_rd(&r, &info, text, PRINTK_MESSAGE_MAX); - len = 0; prb_for_each_record(seq, prb, seq, &r) { int textlen; @@ -2351,22 +2347,6 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre static u64 syslog_seq; -static size_t record_print_text(const struct printk_record *r, - bool syslog, bool time) -{ - return 0; -} -static ssize_t info_print_ext_header(char *buf, size_t size, - struct printk_info *info) -{ - return 0; -} -static ssize_t msg_print_ext_body(char *buf, size_t size, - char *text, size_t text_len, - struct dev_printk_info *dev_info) { return 0; } -static void console_lock_spinning_enable(void) { } -static int console_lock_spinning_disable_and_check(int cookie) { return 0; } -static bool suppress_message_printing(int level) { return false; } static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; } static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; } @@ -2726,6 +2706,8 @@ static void __console_unlock(void) up_console_sem(); } +#ifdef CONFIG_PRINTK + /* * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". This * is achieved by shifting the existing message over and inserting the dropped @@ -2740,8 +2722,7 @@ static void __console_unlock(void) * * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated. */ -#ifdef CONFIG_PRINTK -static void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) +void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) { struct printk_buffers *pbufs = pmsg->pbufs; const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf); @@ -2772,9 +2753,6 @@ static void console_prepend_dropped(struct printk_message *pmsg, unsigned long d memcpy(outbuf, scratchbuf, len); pmsg->outbuf_len += len; } -#else -#define console_prepend_dropped(pmsg, dropped) -#endif /* CONFIG_PRINTK */ /* * Read and format the specified record (or a later record if the specified @@ -2795,8 +2773,8 @@ static void console_prepend_dropped(struct printk_message *pmsg, unsigned long d * of @pmsg are valid. (See the documentation of struct printk_message * for information about the @pmsg fields.) */ -static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, - bool is_extended, bool may_suppress) +bool printk_get_next_message(struct printk_message *pmsg, u64 seq, + bool is_extended, bool may_suppress) { static int panic_console_dropped; @@ -2854,6 +2832,13 @@ out: return true; } +/* + * Used as the printk buffers for non-panic, serialized console printing. + * This is for legacy (!CON_NBCON) as well as all boot (CON_BOOT) consoles. + * Its usage requires the console_lock held. + */ +struct printk_buffers printk_shared_pbufs; + /* * Print one record for the given console. The record printed is whatever * record is the next available record for the given console. @@ -2871,12 +2856,10 @@ out: */ static bool console_emit_next_record(struct console *con, bool *handover, int cookie) { - static struct printk_buffers pbufs; - bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; - char *outbuf = &pbufs.outbuf[0]; + char *outbuf = &printk_shared_pbufs.outbuf[0]; struct printk_message pmsg = { - .pbufs = &pbufs, + .pbufs = &printk_shared_pbufs, }; unsigned long flags; @@ -2927,6 +2910,16 @@ skip: return true; } +#else + +static bool console_emit_next_record(struct console *con, bool *handover, int cookie) +{ + *handover = false; + return false; +} + +#endif /* CONFIG_PRINTK */ + /* * Print out all remaining records to all consoles. * @@ -3171,6 +3164,7 @@ void console_flush_on_panic(enum con_flush_mode mode) if (mode == CONSOLE_REPLAY_ALL) { struct console *c; + short flags; int cookie; u64 seq; @@ -3178,11 +3172,17 @@ void console_flush_on_panic(enum con_flush_mode mode) cookie = console_srcu_read_lock(); for_each_console_srcu(c) { - /* - * This is an unsynchronized assignment, but the - * kernel is in "hope and pray" mode anyway. - */ - c->seq = seq; + flags = console_srcu_read_flags(c); + + if (flags & CON_NBCON) { + nbcon_seq_force(c, seq); + } else { + /* + * This is an unsynchronized assignment. On + * panic legacy consoles are only best effort. + */ + c->seq = seq; + } } console_srcu_read_unlock(cookie); } @@ -3334,11 +3334,6 @@ static void try_enable_default_console(struct console *newcon) newcon->flags |= CON_CONSDEV; } -#define con_printk(lvl, con, fmt, ...) \ - printk(lvl pr_fmt("%sconsole [%s%d] " fmt), \ - (con->flags & CON_BOOT) ? "boot" : "", \ - con->name, con->index, ##__VA_ARGS__) - static void console_init_seq(struct console *newcon, bool bootcon_registered) { struct console *con; @@ -3452,6 +3447,15 @@ void register_console(struct console *newcon) goto unlock; } + if (newcon->flags & CON_NBCON) { + /* + * Ensure the nbcon console buffers can be allocated + * before modifying any global data. + */ + if (!nbcon_alloc(newcon)) + goto unlock; + } + /* * See if we want to enable this console driver by default. * @@ -3479,8 +3483,11 @@ void register_console(struct console *newcon) err = try_enable_preferred_console(newcon, false); /* printk() messages are not printed to the Braille console. */ - if (err || newcon->flags & CON_BRL) + if (err || newcon->flags & CON_BRL) { + if (newcon->flags & CON_NBCON) + nbcon_free(newcon); goto unlock; + } /* * If we have a bootconsole, and are switching to a real console, @@ -3496,6 +3503,9 @@ void register_console(struct console *newcon) newcon->dropped = 0; console_init_seq(newcon, bootcon_registered); + if (newcon->flags & CON_NBCON) + nbcon_init(newcon); + /* * Put this console in the list - keep the * preferred driver at the head of the list. @@ -3587,6 +3597,9 @@ static int unregister_console_locked(struct console *console) */ synchronize_srcu(&console_srcu); + if (console->flags & CON_NBCON) + nbcon_free(console); + console_sysfs_notify(); if (console->exit) @@ -3736,10 +3749,12 @@ late_initcall(printk_late_init); /* If @con is specified, only wait for that console. Otherwise wait for all. */ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { - int remaining = timeout_ms; + unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms); + unsigned long remaining_jiffies = timeout_jiffies; struct console *c; u64 last_diff = 0; u64 printk_seq; + short flags; int cookie; u64 diff; u64 seq; @@ -3753,6 +3768,9 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre console_unlock(); for (;;) { + unsigned long begin_jiffies; + unsigned long slept_jiffies; + diff = 0; /* @@ -3767,6 +3785,9 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre for_each_console_srcu(c) { if (con && con != c) continue; + + flags = console_srcu_read_flags(c); + /* * If consoles are not usable, it cannot be expected * that they make forward progress, so only increment @@ -3774,31 +3795,33 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre */ if (!console_is_usable(c)) continue; - printk_seq = c->seq; + + if (flags & CON_NBCON) { + printk_seq = nbcon_seq_read(c); + } else { + printk_seq = c->seq; + } + if (printk_seq < seq) diff += seq - printk_seq; } console_srcu_read_unlock(cookie); if (diff != last_diff && reset_on_progress) - remaining = timeout_ms; + remaining_jiffies = timeout_jiffies; console_unlock(); /* Note: @diff is 0 if there are no usable consoles. */ - if (diff == 0 || remaining == 0) + if (diff == 0 || remaining_jiffies == 0) break; - if (remaining < 0) { - /* no timeout limit */ - msleep(100); - } else if (remaining < 100) { - msleep(remaining); - remaining = 0; - } else { - msleep(100); - remaining -= 100; - } + /* msleep(1) might sleep much longer. Check time by jiffies. */ + begin_jiffies = jiffies; + msleep(1); + slept_jiffies = jiffies - begin_jiffies; + + remaining_jiffies -= min(slept_jiffies, remaining_jiffies); last_diff = diff; } @@ -4203,7 +4226,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dump_iter *iter, bool syslog, prb_rec_init_rd(&r, &info, buf, size); - len = 0; prb_for_each_record(seq, prb, seq, &r) { if (r.info->seq >= iter->next_seq) break; diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 515cafdb18d9..43cc47d7faaf 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2056,7 +2056,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer) retries = 10; success = false; while (retries--) { - struct list_head *head_page, *prev_page, *r; + struct list_head *head_page, *prev_page; struct list_head *last_page, *first_page; struct list_head *head_page_with_bit; struct buffer_page *hpage = rb_set_head_page(cpu_buffer); @@ -2075,9 +2075,9 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer) last_page->next = head_page_with_bit; first_page->prev = prev_page; - r = cmpxchg(&prev_page->next, head_page_with_bit, first_page); - - if (r == head_page_with_bit) { + /* caution: head_page_with_bit gets updated on cmpxchg failure */ + if (try_cmpxchg(&prev_page->next, + &head_page_with_bit, first_page)) { /* * yay, we replaced the page pointer to our new list, * now, we just have to update to head page's prev diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index abaaf516fcae..9aebf904ff97 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -54,12 +54,6 @@ #include "trace.h" #include "trace_output.h" -/* - * On boot up, the ring buffer is set to the minimum size, so that - * we do not waste memory on systems that are not using tracing. - */ -bool ring_buffer_expanded; - #ifdef CONFIG_FTRACE_STARTUP_TEST /* * We need to change this state when a selftest is running. @@ -202,7 +196,7 @@ static int __init set_cmdline_ftrace(char *str) strscpy(bootup_tracer_buf, str, MAX_TRACER_SIZE); default_bootup_tracer = bootup_tracer_buf; /* We are using ftrace early, expand it */ - ring_buffer_expanded = true; + trace_set_ring_buffer_expanded(NULL); return 1; } __setup("ftrace=", set_cmdline_ftrace); @@ -247,7 +241,7 @@ static int __init boot_alloc_snapshot(char *str) } else { allocate_snapshot = true; /* We also need the main ring buffer expanded */ - ring_buffer_expanded = true; + trace_set_ring_buffer_expanded(NULL); } return 1; } @@ -490,6 +484,13 @@ static struct trace_array global_trace = { .trace_flags = TRACE_DEFAULT_FLAGS, }; +void trace_set_ring_buffer_expanded(struct trace_array *tr) +{ + if (!tr) + tr = &global_trace; + tr->ring_buffer_expanded = true; +} + LIST_HEAD(ftrace_trace_arrays); int trace_array_get(struct trace_array *this_tr) @@ -1730,15 +1731,15 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt) { int len; - if (trace_seq_used(s) <= s->seq.readpos) + if (trace_seq_used(s) <= s->readpos) return -EBUSY; - len = trace_seq_used(s) - s->seq.readpos; + len = trace_seq_used(s) - s->readpos; if (cnt > len) cnt = len; - memcpy(buf, s->buffer + s->seq.readpos, cnt); + memcpy(buf, s->buffer + s->readpos, cnt); - s->seq.readpos += cnt; + s->readpos += cnt; return cnt; } @@ -2012,7 +2013,7 @@ static int run_tracer_selftest(struct tracer *type) #ifdef CONFIG_TRACER_MAX_TRACE if (type->use_max_tr) { /* If we expanded the buffers, make sure the max is expanded too */ - if (ring_buffer_expanded) + if (tr->ring_buffer_expanded) ring_buffer_resize(tr->max_buffer.buffer, trace_buf_size, RING_BUFFER_ALL_CPUS); tr->allocated_snapshot = true; @@ -2038,7 +2039,7 @@ static int run_tracer_selftest(struct tracer *type) tr->allocated_snapshot = false; /* Shrink the max buffer again */ - if (ring_buffer_expanded) + if (tr->ring_buffer_expanded) ring_buffer_resize(tr->max_buffer.buffer, 1, RING_BUFFER_ALL_CPUS); } @@ -3403,7 +3404,7 @@ void trace_printk_init_buffers(void) pr_warn("**********************************************************\n"); /* Expand the buffers to set size */ - tracing_update_buffers(); + tracing_update_buffers(&global_trace); buffers_allocated = 1; @@ -3827,15 +3828,6 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str, return false; } -static const char *show_buffer(struct trace_seq *s) -{ - struct seq_buf *seq = &s->seq; - - seq_buf_terminate(seq); - - return seq->buffer; -} - static DEFINE_STATIC_KEY_FALSE(trace_no_verify); static int test_can_verify_check(const char *fmt, ...) @@ -3975,7 +3967,7 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, */ if (WARN_ONCE(!trace_safe_str(iter, str, star, len), "fmt: '%s' current_buffer: '%s'", - fmt, show_buffer(&iter->seq))) { + fmt, seq_buf_str(&iter->seq.seq))) { int ret; /* Try to safely read the string */ @@ -4986,6 +4978,20 @@ int tracing_open_file_tr(struct inode *inode, struct file *filp) if (ret) return ret; + mutex_lock(&event_mutex); + + /* Fail if the file is marked for removal */ + if (file->flags & EVENT_FILE_FL_FREED) { + trace_array_put(file->tr); + ret = -ENODEV; + } else { + event_file_get(file); + } + + mutex_unlock(&event_mutex); + if (ret) + return ret; + filp->private_data = inode->i_private; return 0; @@ -4996,6 +5002,7 @@ int tracing_release_file_tr(struct inode *inode, struct file *filp) struct trace_event_file *file = inode->i_private; trace_array_put(file->tr); + event_file_put(file); return 0; } @@ -6374,7 +6381,7 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr, * we use the size that was given, and we can forget about * expanding it later. */ - ring_buffer_expanded = true; + trace_set_ring_buffer_expanded(tr); /* May be called before buffers are initialized */ if (!tr->array_buffer.buffer) @@ -6452,6 +6459,7 @@ out: /** * tracing_update_buffers - used by tracing facility to expand ring buffers + * @tr: The tracing instance * * To save on memory when the tracing is never used on a system with it * configured in. The ring buffers are set to a minimum size. But once @@ -6460,13 +6468,13 @@ out: * * This function is to be called when a tracer is about to be used. */ -int tracing_update_buffers(void) +int tracing_update_buffers(struct trace_array *tr) { int ret = 0; mutex_lock(&trace_types_lock); - if (!ring_buffer_expanded) - ret = __tracing_resize_ring_buffer(&global_trace, trace_buf_size, + if (!tr->ring_buffer_expanded) + ret = __tracing_resize_ring_buffer(tr, trace_buf_size, RING_BUFFER_ALL_CPUS); mutex_unlock(&trace_types_lock); @@ -6520,7 +6528,7 @@ int tracing_set_tracer(struct trace_array *tr, const char *buf) mutex_lock(&trace_types_lock); - if (!ring_buffer_expanded) { + if (!tr->ring_buffer_expanded) { ret = __tracing_resize_ring_buffer(tr, trace_buf_size, RING_BUFFER_ALL_CPUS); if (ret < 0) @@ -7006,7 +7014,7 @@ waitagain: /* Now copy what we have to the user */ sret = trace_seq_to_user(&iter->seq, ubuf, cnt); - if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq)) + if (iter->seq.readpos >= trace_seq_used(&iter->seq)) trace_seq_init(&iter->seq); /* @@ -7192,7 +7200,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf, } if (buf_size_same) { - if (!ring_buffer_expanded) + if (!tr->ring_buffer_expanded) r = sprintf(buf, "%lu (expanded: %lu)\n", size >> 10, trace_buf_size >> 10); @@ -7249,10 +7257,10 @@ tracing_total_entries_read(struct file *filp, char __user *ubuf, mutex_lock(&trace_types_lock); for_each_tracing_cpu(cpu) { size += per_cpu_ptr(tr->array_buffer.data, cpu)->entries >> 10; - if (!ring_buffer_expanded) + if (!tr->ring_buffer_expanded) expanded_size += trace_buf_size >> 10; } - if (ring_buffer_expanded) + if (tr->ring_buffer_expanded) r = sprintf(buf, "%lu\n", size); else r = sprintf(buf, "%lu (expanded: %lu)\n", size, expanded_size); @@ -7646,7 +7654,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt, unsigned long val; int ret; - ret = tracing_update_buffers(); + ret = tracing_update_buffers(tr); if (ret < 0) return ret; @@ -9550,6 +9558,9 @@ static struct trace_array *trace_array_create(const char *name) if (allocate_trace_buffers(tr, trace_buf_size) < 0) goto out_free_tr; + /* The ring buffer is defaultly expanded */ + trace_set_ring_buffer_expanded(tr); + if (ftrace_allocate_ftrace_ops(tr) < 0) goto out_free_tr; @@ -9759,7 +9770,6 @@ static __init void create_trace_instances(struct dentry *d_tracer) static void init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) { - struct trace_event_file *file; int cpu; trace_create_file("available_tracers", TRACE_MODE_READ, d_tracer, @@ -9792,11 +9802,7 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) trace_create_file("trace_marker", 0220, d_tracer, tr, &tracing_mark_fops); - file = __find_event_file(tr, "ftrace", "print"); - if (file && file->ef) - eventfs_add_file("trigger", TRACE_MODE_WRITE, file->ef, - file, &event_trigger_fops); - tr->trace_marker_file = file; + tr->trace_marker_file = __find_event_file(tr, "ftrace", "print"); trace_create_file("trace_marker_raw", 0220, d_tracer, tr, &tracing_mark_raw_fops); @@ -10444,7 +10450,7 @@ __init static int tracer_alloc_buffers(void) trace_printk_init_buffers(); /* To save memory, keep the ring buffer size to its minimum */ - if (ring_buffer_expanded) + if (global_trace.ring_buffer_expanded) ring_buf_size = trace_buf_size; else ring_buf_size = 1; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 77debe53f07c..b7f4ea25a194 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -381,7 +381,7 @@ struct trace_array { struct dentry *dir; struct dentry *options; struct dentry *percpu_dir; - struct dentry *event_dir; + struct eventfs_inode *event_dir; struct trace_options *topts; struct list_head systems; struct list_head events; @@ -410,6 +410,11 @@ struct trace_array { struct cond_snapshot *cond_snapshot; #endif struct trace_func_repeats __percpu *last_func_repeats; + /* + * On boot up, the ring buffer is set to the minimum size, so that + * we do not waste memory on systems that are not using tracing. + */ + bool ring_buffer_expanded; }; enum { @@ -761,7 +766,7 @@ extern int DYN_FTRACE_TEST_NAME(void); #define DYN_FTRACE_TEST_NAME2 trace_selftest_dynamic_test_func2 extern int DYN_FTRACE_TEST_NAME2(void); -extern bool ring_buffer_expanded; +extern void trace_set_ring_buffer_expanded(struct trace_array *tr); extern bool tracing_selftest_disabled; #ifdef CONFIG_FTRACE_STARTUP_TEST @@ -1305,7 +1310,7 @@ static inline void trace_branch_disable(void) #endif /* CONFIG_BRANCH_TRACER */ /* set ring buffers to default size if not already done so */ -int tracing_update_buffers(void); +int tracing_update_buffers(struct trace_array *tr); union trace_synth_field { u8 as_u8; @@ -1344,7 +1349,7 @@ struct trace_subsystem_dir { struct list_head list; struct event_subsystem *subsystem; struct trace_array *tr; - struct eventfs_file *ef; + struct eventfs_inode *ei; int ref_count; int nr_events; }; @@ -1664,6 +1669,9 @@ extern void event_trigger_unregister(struct event_command *cmd_ops, char *glob, struct event_trigger_data *trigger_data); +extern void event_file_get(struct trace_event_file *file); +extern void event_file_put(struct trace_event_file *file); + /** * struct event_trigger_ops - callbacks for trace event triggers * diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index f49d6ddb6342..f29e815ca5b2 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -984,19 +984,41 @@ static void remove_subsystem(struct trace_subsystem_dir *dir) return; if (!--dir->nr_events) { - eventfs_remove(dir->ef); + eventfs_remove_dir(dir->ei); list_del(&dir->list); __put_system_dir(dir); } } +void event_file_get(struct trace_event_file *file) +{ + atomic_inc(&file->ref); +} + +void event_file_put(struct trace_event_file *file) +{ + if (WARN_ON_ONCE(!atomic_read(&file->ref))) { + if (file->flags & EVENT_FILE_FL_FREED) + kmem_cache_free(file_cachep, file); + return; + } + + if (atomic_dec_and_test(&file->ref)) { + /* Count should only go to zero when it is freed */ + if (WARN_ON_ONCE(!(file->flags & EVENT_FILE_FL_FREED))) + return; + kmem_cache_free(file_cachep, file); + } +} + static void remove_event_file_dir(struct trace_event_file *file) { - eventfs_remove(file->ef); + eventfs_remove_dir(file->ei); list_del(&file->list); remove_subsystem(file->system); free_event_filter(file->filter); - kmem_cache_free(file_cachep, file); + file->flags |= EVENT_FILE_FL_FREED; + event_file_put(file); } /* @@ -1166,7 +1188,7 @@ ftrace_event_write(struct file *file, const char __user *ubuf, if (!cnt) return 0; - ret = tracing_update_buffers(); + ret = tracing_update_buffers(tr); if (ret < 0) return ret; @@ -1369,7 +1391,7 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, flags = file->flags; mutex_unlock(&event_mutex); - if (!file) + if (!file || flags & EVENT_FILE_FL_FREED) return -ENODEV; if (flags & EVENT_FILE_FL_ENABLED && @@ -1397,18 +1419,20 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, if (ret) return ret; - ret = tracing_update_buffers(); - if (ret < 0) - return ret; - switch (val) { case 0: case 1: ret = -ENODEV; mutex_lock(&event_mutex); file = event_file_data(filp); - if (likely(file)) + if (likely(file && !(file->flags & EVENT_FILE_FL_FREED))) { + ret = tracing_update_buffers(file->tr); + if (ret < 0) { + mutex_unlock(&event_mutex); + return ret; + } ret = ftrace_event_enable_disable(file, val); + } mutex_unlock(&event_mutex); break; @@ -1482,7 +1506,7 @@ system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, if (ret) return ret; - ret = tracing_update_buffers(); + ret = tracing_update_buffers(dir->tr); if (ret < 0) return ret; @@ -1681,7 +1705,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, mutex_lock(&event_mutex); file = event_file_data(filp); - if (file) + if (file && !(file->flags & EVENT_FILE_FL_FREED)) print_event_filter(file, s); mutex_unlock(&event_mutex); @@ -1956,7 +1980,7 @@ event_pid_write(struct file *filp, const char __user *ubuf, if (!cnt) return 0; - ret = tracing_update_buffers(); + ret = tracing_update_buffers(tr); if (ret < 0) return ret; @@ -2280,14 +2304,40 @@ create_new_subsystem(const char *name) return NULL; } -static struct eventfs_file * +static int system_callback(const char *name, umode_t *mode, void **data, + const struct file_operations **fops) +{ + if (strcmp(name, "filter") == 0) + *fops = &ftrace_subsystem_filter_fops; + + else if (strcmp(name, "enable") == 0) + *fops = &ftrace_system_enable_fops; + + else + return 0; + + *mode = TRACE_MODE_WRITE; + return 1; +} + +static struct eventfs_inode * event_subsystem_dir(struct trace_array *tr, const char *name, - struct trace_event_file *file, struct dentry *parent) + struct trace_event_file *file, struct eventfs_inode *parent) { struct event_subsystem *system, *iter; struct trace_subsystem_dir *dir; - struct eventfs_file *ef; - int res; + struct eventfs_inode *ei; + int nr_entries; + static struct eventfs_entry system_entries[] = { + { + .name = "filter", + .callback = system_callback, + }, + { + .name = "enable", + .callback = system_callback, + } + }; /* First see if we did not already create this dir */ list_for_each_entry(dir, &tr->systems, list) { @@ -2295,7 +2345,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name, if (strcmp(system->name, name) == 0) { dir->nr_events++; file->system = dir; - return dir->ef; + return dir->ei; } } @@ -2319,39 +2369,29 @@ event_subsystem_dir(struct trace_array *tr, const char *name, } else __get_system(system); - ef = eventfs_add_subsystem_dir(name, parent); - if (IS_ERR(ef)) { + /* ftrace only has directories no files */ + if (strcmp(name, "ftrace") == 0) + nr_entries = 0; + else + nr_entries = ARRAY_SIZE(system_entries); + + ei = eventfs_create_dir(name, parent, system_entries, nr_entries, dir); + if (IS_ERR(ei)) { pr_warn("Failed to create system directory %s\n", name); __put_system(system); goto out_free; } - dir->ef = ef; + dir->ei = ei; dir->tr = tr; dir->ref_count = 1; dir->nr_events = 1; dir->subsystem = system; file->system = dir; - /* the ftrace system is special, do not create enable or filter files */ - if (strcmp(name, "ftrace") != 0) { - - res = eventfs_add_file("filter", TRACE_MODE_WRITE, - dir->ef, dir, - &ftrace_subsystem_filter_fops); - if (res) { - kfree(system->filter); - system->filter = NULL; - pr_warn("Could not create tracefs '%s/filter' entry\n", name); - } - - eventfs_add_file("enable", TRACE_MODE_WRITE, dir->ef, dir, - &ftrace_system_enable_fops); - } - list_add(&dir->list, &tr->systems); - return dir->ef; + return dir->ei; out_free: kfree(dir); @@ -2400,15 +2440,134 @@ event_define_fields(struct trace_event_call *call) return ret; } +static int event_callback(const char *name, umode_t *mode, void **data, + const struct file_operations **fops) +{ + struct trace_event_file *file = *data; + struct trace_event_call *call = file->event_call; + + if (strcmp(name, "format") == 0) { + *mode = TRACE_MODE_READ; + *fops = &ftrace_event_format_fops; + *data = call; + return 1; + } + + /* + * Only event directories that can be enabled should have + * triggers or filters, with the exception of the "print" + * event that can have a "trigger" file. + */ + if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) { + if (call->class->reg && strcmp(name, "enable") == 0) { + *mode = TRACE_MODE_WRITE; + *fops = &ftrace_enable_fops; + return 1; + } + + if (strcmp(name, "filter") == 0) { + *mode = TRACE_MODE_WRITE; + *fops = &ftrace_event_filter_fops; + return 1; + } + } + + if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) || + strcmp(trace_event_name(call), "print") == 0) { + if (strcmp(name, "trigger") == 0) { + *mode = TRACE_MODE_WRITE; + *fops = &event_trigger_fops; + return 1; + } + } + +#ifdef CONFIG_PERF_EVENTS + if (call->event.type && call->class->reg && + strcmp(name, "id") == 0) { + *mode = TRACE_MODE_READ; + *data = (void *)(long)call->event.type; + *fops = &ftrace_event_id_fops; + return 1; + } +#endif + +#ifdef CONFIG_HIST_TRIGGERS + if (strcmp(name, "hist") == 0) { + *mode = TRACE_MODE_READ; + *fops = &event_hist_fops; + return 1; + } +#endif +#ifdef CONFIG_HIST_TRIGGERS_DEBUG + if (strcmp(name, "hist_debug") == 0) { + *mode = TRACE_MODE_READ; + *fops = &event_hist_debug_fops; + return 1; + } +#endif +#ifdef CONFIG_TRACE_EVENT_INJECT + if (call->event.type && call->class->reg && + strcmp(name, "inject") == 0) { + *mode = 0200; + *fops = &event_inject_fops; + return 1; + } +#endif + return 0; +} + static int -event_create_dir(struct dentry *parent, struct trace_event_file *file) +event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file) { struct trace_event_call *call = file->event_call; - struct eventfs_file *ef_subsystem = NULL; struct trace_array *tr = file->tr; - struct eventfs_file *ef; + struct eventfs_inode *e_events; + struct eventfs_inode *ei; const char *name; + int nr_entries; int ret; + static struct eventfs_entry event_entries[] = { + { + .name = "enable", + .callback = event_callback, + }, + { + .name = "filter", + .callback = event_callback, + }, + { + .name = "trigger", + .callback = event_callback, + }, + { + .name = "format", + .callback = event_callback, + }, +#ifdef CONFIG_PERF_EVENTS + { + .name = "id", + .callback = event_callback, + }, +#endif +#ifdef CONFIG_HIST_TRIGGERS + { + .name = "hist", + .callback = event_callback, + }, +#endif +#ifdef CONFIG_HIST_TRIGGERS_DEBUG + { + .name = "hist_debug", + .callback = event_callback, + }, +#endif +#ifdef CONFIG_TRACE_EVENT_INJECT + { + .name = "inject", + .callback = event_callback, + }, +#endif + }; /* * If the trace point header did not define TRACE_SYSTEM @@ -2418,29 +2577,20 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) if (WARN_ON_ONCE(strcmp(call->class->system, TRACE_SYSTEM) == 0)) return -ENODEV; - ef_subsystem = event_subsystem_dir(tr, call->class->system, file, parent); - if (!ef_subsystem) + e_events = event_subsystem_dir(tr, call->class->system, file, parent); + if (!e_events) return -ENOMEM; + nr_entries = ARRAY_SIZE(event_entries); + name = trace_event_name(call); - ef = eventfs_add_dir(name, ef_subsystem); - if (IS_ERR(ef)) { + ei = eventfs_create_dir(name, e_events, event_entries, nr_entries, file); + if (IS_ERR(ei)) { pr_warn("Could not create tracefs '%s' directory\n", name); return -1; } - file->ef = ef; - - if (call->class->reg && !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) - eventfs_add_file("enable", TRACE_MODE_WRITE, file->ef, file, - &ftrace_enable_fops); - -#ifdef CONFIG_PERF_EVENTS - if (call->event.type && call->class->reg) - eventfs_add_file("id", TRACE_MODE_READ, file->ef, - (void *)(long)call->event.type, - &ftrace_event_id_fops); -#endif + file->ei = ei; ret = event_define_fields(call); if (ret < 0) { @@ -2448,35 +2598,6 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) return ret; } - /* - * Only event directories that can be enabled should have - * triggers or filters. - */ - if (!(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)) { - eventfs_add_file("filter", TRACE_MODE_WRITE, file->ef, - file, &ftrace_event_filter_fops); - - eventfs_add_file("trigger", TRACE_MODE_WRITE, file->ef, - file, &event_trigger_fops); - } - -#ifdef CONFIG_HIST_TRIGGERS - eventfs_add_file("hist", TRACE_MODE_READ, file->ef, file, - &event_hist_fops); -#endif -#ifdef CONFIG_HIST_TRIGGERS_DEBUG - eventfs_add_file("hist_debug", TRACE_MODE_READ, file->ef, file, - &event_hist_debug_fops); -#endif - eventfs_add_file("format", TRACE_MODE_READ, file->ef, call, - &ftrace_event_format_fops); - -#ifdef CONFIG_TRACE_EVENT_INJECT - if (call->event.type && call->class->reg) - eventfs_add_file("inject", 0200, file->ef, file, - &event_inject_fops); -#endif - return 0; } @@ -2803,6 +2924,7 @@ trace_create_new_event(struct trace_event_call *call, atomic_set(&file->tm_ref, 0); INIT_LIST_HEAD(&file->triggers); list_add(&file->list, &tr->events); + event_file_get(file); return file; } @@ -2824,7 +2946,7 @@ static __init int setup_trace_triggers(char *str) int i; strscpy(bootup_trigger_buf, str, COMMAND_LINE_SIZE); - ring_buffer_expanded = true; + trace_set_ring_buffer_expanded(NULL); disable_tracing_selftest("running event triggers"); buf = bootup_trigger_buf; @@ -3614,37 +3736,72 @@ static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata; static __init int setup_trace_event(char *str) { strscpy(bootup_event_buf, str, COMMAND_LINE_SIZE); - ring_buffer_expanded = true; + trace_set_ring_buffer_expanded(NULL); disable_tracing_selftest("running event tracing"); return 1; } __setup("trace_event=", setup_trace_event); +static int events_callback(const char *name, umode_t *mode, void **data, + const struct file_operations **fops) +{ + if (strcmp(name, "enable") == 0) { + *mode = TRACE_MODE_WRITE; + *fops = &ftrace_tr_enable_fops; + return 1; + } + + if (strcmp(name, "header_page") == 0) + *data = ring_buffer_print_page_header; + + else if (strcmp(name, "header_event") == 0) + *data = ring_buffer_print_entry_header; + + else + return 0; + + *mode = TRACE_MODE_READ; + *fops = &ftrace_show_header_fops; + return 1; +} + /* Expects to have event_mutex held when called */ static int create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) { - struct dentry *d_events; + struct eventfs_inode *e_events; struct dentry *entry; - int error = 0; + int nr_entries; + static struct eventfs_entry events_entries[] = { + { + .name = "enable", + .callback = events_callback, + }, + { + .name = "header_page", + .callback = events_callback, + }, + { + .name = "header_event", + .callback = events_callback, + }, + }; entry = trace_create_file("set_event", TRACE_MODE_WRITE, parent, tr, &ftrace_set_event_fops); if (!entry) return -ENOMEM; - d_events = eventfs_create_events_dir("events", parent); - if (IS_ERR(d_events)) { + nr_entries = ARRAY_SIZE(events_entries); + + e_events = eventfs_create_events_dir("events", parent, events_entries, + nr_entries, tr); + if (IS_ERR(e_events)) { pr_warn("Could not create tracefs 'events' directory\n"); return -ENOMEM; } - error = eventfs_add_events_file("enable", TRACE_MODE_WRITE, d_events, - tr, &ftrace_tr_enable_fops); - if (error) - return -ENOMEM; - /* There are not as crucial, just warn if they are not created */ trace_create_file("set_event_pid", TRACE_MODE_WRITE, parent, @@ -3654,16 +3811,7 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) TRACE_MODE_WRITE, parent, tr, &ftrace_set_event_notrace_pid_fops); - /* ring buffer internal formats */ - eventfs_add_events_file("header_page", TRACE_MODE_READ, d_events, - ring_buffer_print_page_header, - &ftrace_show_header_fops); - - eventfs_add_events_file("header_event", TRACE_MODE_READ, d_events, - ring_buffer_print_entry_header, - &ftrace_show_header_fops); - - tr->event_dir = d_events; + tr->event_dir = e_events; return 0; } diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 33264e510d16..0c611b281a5b 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -2349,6 +2349,9 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string) struct event_filter *filter = NULL; int err; + if (file->flags & EVENT_FILE_FL_FREED) + return -ENODEV; + if (!strcmp(strstrip(filter_string), "0")) { filter_disable(file); filter = event_filter(file); diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index d06938ae0717..1abc07fba1b9 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -774,23 +774,16 @@ static void last_cmd_set(struct trace_event_file *file, char *str) { const char *system = NULL, *name = NULL; struct trace_event_call *call; - int len; if (!str) return; - /* sizeof() contains the nul byte */ - len = sizeof(HIST_PREFIX) + strlen(str); kfree(last_cmd); - last_cmd = kzalloc(len, GFP_KERNEL); + + last_cmd = kasprintf(GFP_KERNEL, HIST_PREFIX "%s", str); if (!last_cmd) return; - strcpy(last_cmd, HIST_PREFIX); - /* Again, sizeof() contains the nul byte */ - len -= sizeof(HIST_PREFIX); - strncat(last_cmd, str, len); - if (file) { call = file->event_call; system = call->class->system; diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c index 14cb275a0bab..846e02c0fb59 100644 --- a/kernel/trace/trace_events_synth.c +++ b/kernel/trace/trace_events_synth.c @@ -452,7 +452,7 @@ static unsigned int trace_string(struct synth_trace_event *entry, #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if ((unsigned long)str_val < TASK_SIZE) - ret = strncpy_from_user_nofault(str_field, str_val, STR_VAR_LEN_MAX); + ret = strncpy_from_user_nofault(str_field, (const void __user *)str_val, STR_VAR_LEN_MAX); else #endif ret = strncpy_from_kernel_nofault(str_field, str_val, STR_VAR_LEN_MAX); diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index b87f41187c6a..9365ce407426 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -49,18 +49,6 @@ #define EVENT_STATUS_PERF BIT(1) #define EVENT_STATUS_OTHER BIT(7) -/* - * User register flags are not allowed yet, keep them here until we are - * ready to expose them out to the user ABI. - */ -enum user_reg_flag { - /* Event will not delete upon last reference closing */ - USER_EVENT_REG_PERSIST = 1U << 0, - - /* This value or above is currently non-ABI */ - USER_EVENT_REG_MAX = 1U << 1, -}; - /* * Stores the system name, tables, and locks for a group of events. This * allows isolation for events by various means. @@ -220,6 +208,17 @@ static u32 user_event_key(char *name) return jhash(name, strlen(name), 0); } +static bool user_event_capable(u16 reg_flags) +{ + /* Persistent events require CAP_PERFMON / CAP_SYS_ADMIN */ + if (reg_flags & USER_EVENT_REG_PERSIST) { + if (!perfmon_capable()) + return false; + } + + return true; +} + static struct user_event *user_event_get(struct user_event *user) { refcount_inc(&user->refcnt); @@ -1811,6 +1810,9 @@ static int user_event_free(struct dyn_event *ev) if (!user_event_last_ref(user)) return -EBUSY; + if (!user_event_capable(user->reg_flags)) + return -EPERM; + return destroy_user_event(user); } @@ -1926,10 +1928,13 @@ static int user_event_parse(struct user_event_group *group, char *name, int argc = 0; char **argv; - /* User register flags are not ready yet */ - if (reg_flags != 0 || flags != NULL) + /* Currently don't support any text based flags */ + if (flags != NULL) return -EINVAL; + if (!user_event_capable(reg_flags)) + return -EPERM; + /* Prevent dyn_event from racing */ mutex_lock(&event_mutex); user = find_user_event(group, name, &key); @@ -2062,6 +2067,9 @@ static int delete_user_event(struct user_event_group *group, char *name) if (!user_event_last_ref(user)) return -EBUSY; + if (!user_event_capable(user->reg_flags)) + return -EPERM; + return destroy_user_event(user); } diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c index bac06ee3b98b..7be97229ddf8 100644 --- a/kernel/trace/trace_seq.c +++ b/kernel/trace/trace_seq.c @@ -370,8 +370,12 @@ EXPORT_SYMBOL_GPL(trace_seq_path); */ int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt) { + int ret; __trace_seq_init(s); - return seq_buf_to_user(&s->seq, ubuf, cnt); + ret = seq_buf_to_user(&s->seq, ubuf, s->readpos, cnt); + if (ret > 0) + s->readpos += ret; + return ret; } EXPORT_SYMBOL_GPL(trace_seq_to_user); diff --git a/lib/Makefile b/lib/Makefile index 9e0972f7b764..13455f47f9df 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -48,7 +48,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \ bsearch.o find_bit.o llist.o lwq.o memweight.o kfifo.o \ percpu-refcount.o rhashtable.o base64.o \ once.o refcount.o rcuref.o usercopy.o errseq.o bucket_locks.o \ - generic-radix-tree.o + generic-radix-tree.o bitmap-str.o obj-$(CONFIG_STRING_SELFTEST) += test_string.o obj-y += string_helpers.o obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o diff --git a/lib/bitmap-str.c b/lib/bitmap-str.c new file mode 100644 index 000000000000..be745209507a --- /dev/null +++ b/lib/bitmap-str.c @@ -0,0 +1,510 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kstrtox.h" + +/** + * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap + * + * @ubuf: pointer to user buffer containing string. + * @ulen: buffer size in bytes. If string is smaller than this + * then it must be terminated with a \0. + * @maskp: pointer to bitmap array that will contain result. + * @nmaskbits: size of bitmap, in bits. + */ +int bitmap_parse_user(const char __user *ubuf, + unsigned int ulen, unsigned long *maskp, + int nmaskbits) +{ + char *buf; + int ret; + + buf = memdup_user_nul(ubuf, ulen); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + ret = bitmap_parse(buf, UINT_MAX, maskp, nmaskbits); + + kfree(buf); + return ret; +} +EXPORT_SYMBOL(bitmap_parse_user); + +/** + * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string + * @list: indicates whether the bitmap must be list + * @buf: page aligned buffer into which string is placed + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * + * Output format is a comma-separated list of decimal numbers and + * ranges if list is specified or hex digits grouped into comma-separated + * sets of 8 digits/set. Returns the number of characters written to buf. + * + * It is assumed that @buf is a pointer into a PAGE_SIZE, page-aligned + * area and that sufficient storage remains at @buf to accommodate the + * bitmap_print_to_pagebuf() output. Returns the number of characters + * actually printed to @buf, excluding terminating '\0'. + */ +int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp, + int nmaskbits) +{ + ptrdiff_t len = PAGE_SIZE - offset_in_page(buf); + + return list ? scnprintf(buf, len, "%*pbl\n", nmaskbits, maskp) : + scnprintf(buf, len, "%*pb\n", nmaskbits, maskp); +} +EXPORT_SYMBOL(bitmap_print_to_pagebuf); + +/** + * bitmap_print_to_buf - convert bitmap to list or hex format ASCII string + * @list: indicates whether the bitmap must be list + * true: print in decimal list format + * false: print in hexadecimal bitmask format + * @buf: buffer into which string is placed + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * @off: in the string from which we are copying, We copy to @buf + * @count: the maximum number of bytes to print + */ +static int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp, + int nmaskbits, loff_t off, size_t count) +{ + const char *fmt = list ? "%*pbl\n" : "%*pb\n"; + ssize_t size; + void *data; + + data = kasprintf(GFP_KERNEL, fmt, nmaskbits, maskp); + if (!data) + return -ENOMEM; + + size = memory_read_from_buffer(buf, count, &off, data, strlen(data) + 1); + kfree(data); + + return size; +} + +/** + * bitmap_print_bitmask_to_buf - convert bitmap to hex bitmask format ASCII string + * @buf: buffer into which string is placed + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * @off: in the string from which we are copying, We copy to @buf + * @count: the maximum number of bytes to print + * + * The bitmap_print_to_pagebuf() is used indirectly via its cpumap wrapper + * cpumap_print_to_pagebuf() or directly by drivers to export hexadecimal + * bitmask and decimal list to userspace by sysfs ABI. + * Drivers might be using a normal attribute for this kind of ABIs. A + * normal attribute typically has show entry as below:: + * + * static ssize_t example_attribute_show(struct device *dev, + * struct device_attribute *attr, char *buf) + * { + * ... + * return bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max); + * } + * + * show entry of attribute has no offset and count parameters and this + * means the file is limited to one page only. + * bitmap_print_to_pagebuf() API works terribly well for this kind of + * normal attribute with buf parameter and without offset, count:: + * + * bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp, + * int nmaskbits) + * { + * } + * + * The problem is once we have a large bitmap, we have a chance to get a + * bitmask or list more than one page. Especially for list, it could be + * as complex as 0,3,5,7,9,... We have no simple way to know it exact size. + * It turns out bin_attribute is a way to break this limit. bin_attribute + * has show entry as below:: + * + * static ssize_t + * example_bin_attribute_show(struct file *filp, struct kobject *kobj, + * struct bin_attribute *attr, char *buf, + * loff_t offset, size_t count) + * { + * ... + * } + * + * With the new offset and count parameters, this makes sysfs ABI be able + * to support file size more than one page. For example, offset could be + * >= 4096. + * bitmap_print_bitmask_to_buf(), bitmap_print_list_to_buf() wit their + * cpumap wrapper cpumap_print_bitmask_to_buf(), cpumap_print_list_to_buf() + * make those drivers be able to support large bitmask and list after they + * move to use bin_attribute. In result, we have to pass the corresponding + * parameters such as off, count from bin_attribute show entry to this API. + * + * The role of cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf() + * is similar with cpumap_print_to_pagebuf(), the difference is that + * bitmap_print_to_pagebuf() mainly serves sysfs attribute with the assumption + * the destination buffer is exactly one page and won't be more than one page. + * cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf(), on the other + * hand, mainly serves bin_attribute which doesn't work with exact one page, + * and it can break the size limit of converted decimal list and hexadecimal + * bitmask. + * + * WARNING! + * + * This function is not a replacement for sprintf() or bitmap_print_to_pagebuf(). + * It is intended to workaround sysfs limitations discussed above and should be + * used carefully in general case for the following reasons: + * + * - Time complexity is O(nbits^2/count), comparing to O(nbits) for snprintf(). + * - Memory complexity is O(nbits), comparing to O(1) for snprintf(). + * - @off and @count are NOT offset and number of bits to print. + * - If printing part of bitmap as list, the resulting string is not a correct + * list representation of bitmap. Particularly, some bits within or out of + * related interval may be erroneously set or unset. The format of the string + * may be broken, so bitmap_parselist-like parser may fail parsing it. + * - If printing the whole bitmap as list by parts, user must ensure the order + * of calls of the function such that the offset is incremented linearly. + * - If printing the whole bitmap as list by parts, user must keep bitmap + * unchanged between the very first and very last call. Otherwise concatenated + * result may be incorrect, and format may be broken. + * + * Returns the number of characters actually printed to @buf + */ +int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp, + int nmaskbits, loff_t off, size_t count) +{ + return bitmap_print_to_buf(false, buf, maskp, nmaskbits, off, count); +} +EXPORT_SYMBOL(bitmap_print_bitmask_to_buf); + +/** + * bitmap_print_list_to_buf - convert bitmap to decimal list format ASCII string + * @buf: buffer into which string is placed + * @maskp: pointer to bitmap to convert + * @nmaskbits: size of bitmap, in bits + * @off: in the string from which we are copying, We copy to @buf + * @count: the maximum number of bytes to print + * + * Everything is same with the above bitmap_print_bitmask_to_buf() except + * the print format. + */ +int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp, + int nmaskbits, loff_t off, size_t count) +{ + return bitmap_print_to_buf(true, buf, maskp, nmaskbits, off, count); +} +EXPORT_SYMBOL(bitmap_print_list_to_buf); + +/* + * Region 9-38:4/10 describes the following bitmap structure: + * 0 9 12 18 38 N + * .........****......****......****.................. + * ^ ^ ^ ^ ^ + * start off group_len end nbits + */ +struct region { + unsigned int start; + unsigned int off; + unsigned int group_len; + unsigned int end; + unsigned int nbits; +}; + +static void bitmap_set_region(const struct region *r, unsigned long *bitmap) +{ + unsigned int start; + + for (start = r->start; start <= r->end; start += r->group_len) + bitmap_set(bitmap, start, min(r->end - start + 1, r->off)); +} + +static int bitmap_check_region(const struct region *r) +{ + if (r->start > r->end || r->group_len == 0 || r->off > r->group_len) + return -EINVAL; + + if (r->end >= r->nbits) + return -ERANGE; + + return 0; +} + +static const char *bitmap_getnum(const char *str, unsigned int *num, + unsigned int lastbit) +{ + unsigned long long n; + unsigned int len; + + if (str[0] == 'N') { + *num = lastbit; + return str + 1; + } + + len = _parse_integer(str, 10, &n); + if (!len) + return ERR_PTR(-EINVAL); + if (len & KSTRTOX_OVERFLOW || n != (unsigned int)n) + return ERR_PTR(-EOVERFLOW); + + *num = n; + return str + len; +} + +static inline bool end_of_str(char c) +{ + return c == '\0' || c == '\n'; +} + +static inline bool __end_of_region(char c) +{ + return isspace(c) || c == ','; +} + +static inline bool end_of_region(char c) +{ + return __end_of_region(c) || end_of_str(c); +} + +/* + * The format allows commas and whitespaces at the beginning + * of the region. + */ +static const char *bitmap_find_region(const char *str) +{ + while (__end_of_region(*str)) + str++; + + return end_of_str(*str) ? NULL : str; +} + +static const char *bitmap_find_region_reverse(const char *start, const char *end) +{ + while (start <= end && __end_of_region(*end)) + end--; + + return end; +} + +static const char *bitmap_parse_region(const char *str, struct region *r) +{ + unsigned int lastbit = r->nbits - 1; + + if (!strncasecmp(str, "all", 3)) { + r->start = 0; + r->end = lastbit; + str += 3; + + goto check_pattern; + } + + str = bitmap_getnum(str, &r->start, lastbit); + if (IS_ERR(str)) + return str; + + if (end_of_region(*str)) + goto no_end; + + if (*str != '-') + return ERR_PTR(-EINVAL); + + str = bitmap_getnum(str + 1, &r->end, lastbit); + if (IS_ERR(str)) + return str; + +check_pattern: + if (end_of_region(*str)) + goto no_pattern; + + if (*str != ':') + return ERR_PTR(-EINVAL); + + str = bitmap_getnum(str + 1, &r->off, lastbit); + if (IS_ERR(str)) + return str; + + if (*str != '/') + return ERR_PTR(-EINVAL); + + return bitmap_getnum(str + 1, &r->group_len, lastbit); + +no_end: + r->end = r->start; +no_pattern: + r->off = r->end + 1; + r->group_len = r->end + 1; + + return end_of_str(*str) ? NULL : str; +} + +/** + * bitmap_parselist - convert list format ASCII string to bitmap + * @buf: read user string from this buffer; must be terminated + * with a \0 or \n. + * @maskp: write resulting mask here + * @nmaskbits: number of bits in mask to be written + * + * Input format is a comma-separated list of decimal numbers and + * ranges. Consecutively set bits are shown as two hyphen-separated + * decimal numbers, the smallest and largest bit numbers set in + * the range. + * Optionally each range can be postfixed to denote that only parts of it + * should be set. The range will divided to groups of specific size. + * From each group will be used only defined amount of bits. + * Syntax: range:used_size/group_size + * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769 + * The value 'N' can be used as a dynamically substituted token for the + * maximum allowed value; i.e (nmaskbits - 1). Keep in mind that it is + * dynamic, so if system changes cause the bitmap width to change, such + * as more cores in a CPU list, then any ranges using N will also change. + * + * Returns: 0 on success, -errno on invalid input strings. Error values: + * + * - ``-EINVAL``: wrong region format + * - ``-EINVAL``: invalid character in string + * - ``-ERANGE``: bit number specified too large for mask + * - ``-EOVERFLOW``: integer overflow in the input parameters + */ +int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits) +{ + struct region r; + long ret; + + r.nbits = nmaskbits; + bitmap_zero(maskp, r.nbits); + + while (buf) { + buf = bitmap_find_region(buf); + if (buf == NULL) + return 0; + + buf = bitmap_parse_region(buf, &r); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + ret = bitmap_check_region(&r); + if (ret) + return ret; + + bitmap_set_region(&r, maskp); + } + + return 0; +} +EXPORT_SYMBOL(bitmap_parselist); + + +/** + * bitmap_parselist_user() - convert user buffer's list format ASCII + * string to bitmap + * + * @ubuf: pointer to user buffer containing string. + * @ulen: buffer size in bytes. If string is smaller than this + * then it must be terminated with a \0. + * @maskp: pointer to bitmap array that will contain result. + * @nmaskbits: size of bitmap, in bits. + * + * Wrapper for bitmap_parselist(), providing it with user buffer. + */ +int bitmap_parselist_user(const char __user *ubuf, + unsigned int ulen, unsigned long *maskp, + int nmaskbits) +{ + char *buf; + int ret; + + buf = memdup_user_nul(ubuf, ulen); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + ret = bitmap_parselist(buf, maskp, nmaskbits); + + kfree(buf); + return ret; +} +EXPORT_SYMBOL(bitmap_parselist_user); + +static const char *bitmap_get_x32_reverse(const char *start, + const char *end, u32 *num) +{ + u32 ret = 0; + int c, i; + + for (i = 0; i < 32; i += 4) { + c = hex_to_bin(*end--); + if (c < 0) + return ERR_PTR(-EINVAL); + + ret |= c << i; + + if (start > end || __end_of_region(*end)) + goto out; + } + + if (hex_to_bin(*end--) >= 0) + return ERR_PTR(-EOVERFLOW); +out: + *num = ret; + return end; +} + +/** + * bitmap_parse - convert an ASCII hex string into a bitmap. + * @start: pointer to buffer containing string. + * @buflen: buffer size in bytes. If string is smaller than this + * then it must be terminated with a \0 or \n. In that case, + * UINT_MAX may be provided instead of string length. + * @maskp: pointer to bitmap array that will contain result. + * @nmaskbits: size of bitmap, in bits. + * + * Commas group hex digits into chunks. Each chunk defines exactly 32 + * bits of the resultant bitmask. No chunk may specify a value larger + * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value + * then leading 0-bits are prepended. %-EINVAL is returned for illegal + * characters. Grouping such as "1,,5", ",44", "," or "" is allowed. + * Leading, embedded and trailing whitespace accepted. + */ +int bitmap_parse(const char *start, unsigned int buflen, + unsigned long *maskp, int nmaskbits) +{ + const char *end = strnchrnul(start, buflen, '\n') - 1; + int chunks = BITS_TO_U32(nmaskbits); + u32 *bitmap = (u32 *)maskp; + int unset_bit; + int chunk; + + for (chunk = 0; ; chunk++) { + end = bitmap_find_region_reverse(start, end); + if (start > end) + break; + + if (!chunks--) + return -EOVERFLOW; + +#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN) + end = bitmap_get_x32_reverse(start, end, &bitmap[chunk ^ 1]); +#else + end = bitmap_get_x32_reverse(start, end, &bitmap[chunk]); +#endif + if (IS_ERR(end)) + return PTR_ERR(end); + } + + unset_bit = (BITS_TO_U32(nmaskbits) - chunks) * 32; + if (unset_bit < nmaskbits) { + bitmap_clear(maskp, unset_bit, nmaskbits - unset_bit); + return 0; + } + + if (find_next_bit(maskp, unset_bit, nmaskbits) != unset_bit) + return -EOVERFLOW; + + return 0; +} +EXPORT_SYMBOL(bitmap_parse); diff --git a/lib/bitmap.c b/lib/bitmap.c index ddb31015e38a..09522af227f1 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -6,21 +6,10 @@ #include #include -#include #include #include -#include #include -#include -#include #include -#include -#include -#include - -#include - -#include "kstrtox.h" /** * DOC: bitmap introduction @@ -440,508 +429,6 @@ again: } EXPORT_SYMBOL(bitmap_find_next_zero_area_off); -/* - * Bitmap printing & parsing functions: first version by Nadia Yvette Chambers, - * second version by Paul Jackson, third by Joe Korty. - */ - -/** - * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap - * - * @ubuf: pointer to user buffer containing string. - * @ulen: buffer size in bytes. If string is smaller than this - * then it must be terminated with a \0. - * @maskp: pointer to bitmap array that will contain result. - * @nmaskbits: size of bitmap, in bits. - */ -int bitmap_parse_user(const char __user *ubuf, - unsigned int ulen, unsigned long *maskp, - int nmaskbits) -{ - char *buf; - int ret; - - buf = memdup_user_nul(ubuf, ulen); - if (IS_ERR(buf)) - return PTR_ERR(buf); - - ret = bitmap_parse(buf, UINT_MAX, maskp, nmaskbits); - - kfree(buf); - return ret; -} -EXPORT_SYMBOL(bitmap_parse_user); - -/** - * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string - * @list: indicates whether the bitmap must be list - * @buf: page aligned buffer into which string is placed - * @maskp: pointer to bitmap to convert - * @nmaskbits: size of bitmap, in bits - * - * Output format is a comma-separated list of decimal numbers and - * ranges if list is specified or hex digits grouped into comma-separated - * sets of 8 digits/set. Returns the number of characters written to buf. - * - * It is assumed that @buf is a pointer into a PAGE_SIZE, page-aligned - * area and that sufficient storage remains at @buf to accommodate the - * bitmap_print_to_pagebuf() output. Returns the number of characters - * actually printed to @buf, excluding terminating '\0'. - */ -int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp, - int nmaskbits) -{ - ptrdiff_t len = PAGE_SIZE - offset_in_page(buf); - - return list ? scnprintf(buf, len, "%*pbl\n", nmaskbits, maskp) : - scnprintf(buf, len, "%*pb\n", nmaskbits, maskp); -} -EXPORT_SYMBOL(bitmap_print_to_pagebuf); - -/** - * bitmap_print_to_buf - convert bitmap to list or hex format ASCII string - * @list: indicates whether the bitmap must be list - * true: print in decimal list format - * false: print in hexadecimal bitmask format - * @buf: buffer into which string is placed - * @maskp: pointer to bitmap to convert - * @nmaskbits: size of bitmap, in bits - * @off: in the string from which we are copying, We copy to @buf - * @count: the maximum number of bytes to print - */ -static int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp, - int nmaskbits, loff_t off, size_t count) -{ - const char *fmt = list ? "%*pbl\n" : "%*pb\n"; - ssize_t size; - void *data; - - data = kasprintf(GFP_KERNEL, fmt, nmaskbits, maskp); - if (!data) - return -ENOMEM; - - size = memory_read_from_buffer(buf, count, &off, data, strlen(data) + 1); - kfree(data); - - return size; -} - -/** - * bitmap_print_bitmask_to_buf - convert bitmap to hex bitmask format ASCII string - * @buf: buffer into which string is placed - * @maskp: pointer to bitmap to convert - * @nmaskbits: size of bitmap, in bits - * @off: in the string from which we are copying, We copy to @buf - * @count: the maximum number of bytes to print - * - * The bitmap_print_to_pagebuf() is used indirectly via its cpumap wrapper - * cpumap_print_to_pagebuf() or directly by drivers to export hexadecimal - * bitmask and decimal list to userspace by sysfs ABI. - * Drivers might be using a normal attribute for this kind of ABIs. A - * normal attribute typically has show entry as below:: - * - * static ssize_t example_attribute_show(struct device *dev, - * struct device_attribute *attr, char *buf) - * { - * ... - * return bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max); - * } - * - * show entry of attribute has no offset and count parameters and this - * means the file is limited to one page only. - * bitmap_print_to_pagebuf() API works terribly well for this kind of - * normal attribute with buf parameter and without offset, count:: - * - * bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp, - * int nmaskbits) - * { - * } - * - * The problem is once we have a large bitmap, we have a chance to get a - * bitmask or list more than one page. Especially for list, it could be - * as complex as 0,3,5,7,9,... We have no simple way to know it exact size. - * It turns out bin_attribute is a way to break this limit. bin_attribute - * has show entry as below:: - * - * static ssize_t - * example_bin_attribute_show(struct file *filp, struct kobject *kobj, - * struct bin_attribute *attr, char *buf, - * loff_t offset, size_t count) - * { - * ... - * } - * - * With the new offset and count parameters, this makes sysfs ABI be able - * to support file size more than one page. For example, offset could be - * >= 4096. - * bitmap_print_bitmask_to_buf(), bitmap_print_list_to_buf() wit their - * cpumap wrapper cpumap_print_bitmask_to_buf(), cpumap_print_list_to_buf() - * make those drivers be able to support large bitmask and list after they - * move to use bin_attribute. In result, we have to pass the corresponding - * parameters such as off, count from bin_attribute show entry to this API. - * - * The role of cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf() - * is similar with cpumap_print_to_pagebuf(), the difference is that - * bitmap_print_to_pagebuf() mainly serves sysfs attribute with the assumption - * the destination buffer is exactly one page and won't be more than one page. - * cpumap_print_bitmask_to_buf() and cpumap_print_list_to_buf(), on the other - * hand, mainly serves bin_attribute which doesn't work with exact one page, - * and it can break the size limit of converted decimal list and hexadecimal - * bitmask. - * - * WARNING! - * - * This function is not a replacement for sprintf() or bitmap_print_to_pagebuf(). - * It is intended to workaround sysfs limitations discussed above and should be - * used carefully in general case for the following reasons: - * - * - Time complexity is O(nbits^2/count), comparing to O(nbits) for snprintf(). - * - Memory complexity is O(nbits), comparing to O(1) for snprintf(). - * - @off and @count are NOT offset and number of bits to print. - * - If printing part of bitmap as list, the resulting string is not a correct - * list representation of bitmap. Particularly, some bits within or out of - * related interval may be erroneously set or unset. The format of the string - * may be broken, so bitmap_parselist-like parser may fail parsing it. - * - If printing the whole bitmap as list by parts, user must ensure the order - * of calls of the function such that the offset is incremented linearly. - * - If printing the whole bitmap as list by parts, user must keep bitmap - * unchanged between the very first and very last call. Otherwise concatenated - * result may be incorrect, and format may be broken. - * - * Returns the number of characters actually printed to @buf - */ -int bitmap_print_bitmask_to_buf(char *buf, const unsigned long *maskp, - int nmaskbits, loff_t off, size_t count) -{ - return bitmap_print_to_buf(false, buf, maskp, nmaskbits, off, count); -} -EXPORT_SYMBOL(bitmap_print_bitmask_to_buf); - -/** - * bitmap_print_list_to_buf - convert bitmap to decimal list format ASCII string - * @buf: buffer into which string is placed - * @maskp: pointer to bitmap to convert - * @nmaskbits: size of bitmap, in bits - * @off: in the string from which we are copying, We copy to @buf - * @count: the maximum number of bytes to print - * - * Everything is same with the above bitmap_print_bitmask_to_buf() except - * the print format. - */ -int bitmap_print_list_to_buf(char *buf, const unsigned long *maskp, - int nmaskbits, loff_t off, size_t count) -{ - return bitmap_print_to_buf(true, buf, maskp, nmaskbits, off, count); -} -EXPORT_SYMBOL(bitmap_print_list_to_buf); - -/* - * Region 9-38:4/10 describes the following bitmap structure: - * 0 9 12 18 38 N - * .........****......****......****.................. - * ^ ^ ^ ^ ^ - * start off group_len end nbits - */ -struct region { - unsigned int start; - unsigned int off; - unsigned int group_len; - unsigned int end; - unsigned int nbits; -}; - -static void bitmap_set_region(const struct region *r, unsigned long *bitmap) -{ - unsigned int start; - - for (start = r->start; start <= r->end; start += r->group_len) - bitmap_set(bitmap, start, min(r->end - start + 1, r->off)); -} - -static int bitmap_check_region(const struct region *r) -{ - if (r->start > r->end || r->group_len == 0 || r->off > r->group_len) - return -EINVAL; - - if (r->end >= r->nbits) - return -ERANGE; - - return 0; -} - -static const char *bitmap_getnum(const char *str, unsigned int *num, - unsigned int lastbit) -{ - unsigned long long n; - unsigned int len; - - if (str[0] == 'N') { - *num = lastbit; - return str + 1; - } - - len = _parse_integer(str, 10, &n); - if (!len) - return ERR_PTR(-EINVAL); - if (len & KSTRTOX_OVERFLOW || n != (unsigned int)n) - return ERR_PTR(-EOVERFLOW); - - *num = n; - return str + len; -} - -static inline bool end_of_str(char c) -{ - return c == '\0' || c == '\n'; -} - -static inline bool __end_of_region(char c) -{ - return isspace(c) || c == ','; -} - -static inline bool end_of_region(char c) -{ - return __end_of_region(c) || end_of_str(c); -} - -/* - * The format allows commas and whitespaces at the beginning - * of the region. - */ -static const char *bitmap_find_region(const char *str) -{ - while (__end_of_region(*str)) - str++; - - return end_of_str(*str) ? NULL : str; -} - -static const char *bitmap_find_region_reverse(const char *start, const char *end) -{ - while (start <= end && __end_of_region(*end)) - end--; - - return end; -} - -static const char *bitmap_parse_region(const char *str, struct region *r) -{ - unsigned int lastbit = r->nbits - 1; - - if (!strncasecmp(str, "all", 3)) { - r->start = 0; - r->end = lastbit; - str += 3; - - goto check_pattern; - } - - str = bitmap_getnum(str, &r->start, lastbit); - if (IS_ERR(str)) - return str; - - if (end_of_region(*str)) - goto no_end; - - if (*str != '-') - return ERR_PTR(-EINVAL); - - str = bitmap_getnum(str + 1, &r->end, lastbit); - if (IS_ERR(str)) - return str; - -check_pattern: - if (end_of_region(*str)) - goto no_pattern; - - if (*str != ':') - return ERR_PTR(-EINVAL); - - str = bitmap_getnum(str + 1, &r->off, lastbit); - if (IS_ERR(str)) - return str; - - if (*str != '/') - return ERR_PTR(-EINVAL); - - return bitmap_getnum(str + 1, &r->group_len, lastbit); - -no_end: - r->end = r->start; -no_pattern: - r->off = r->end + 1; - r->group_len = r->end + 1; - - return end_of_str(*str) ? NULL : str; -} - -/** - * bitmap_parselist - convert list format ASCII string to bitmap - * @buf: read user string from this buffer; must be terminated - * with a \0 or \n. - * @maskp: write resulting mask here - * @nmaskbits: number of bits in mask to be written - * - * Input format is a comma-separated list of decimal numbers and - * ranges. Consecutively set bits are shown as two hyphen-separated - * decimal numbers, the smallest and largest bit numbers set in - * the range. - * Optionally each range can be postfixed to denote that only parts of it - * should be set. The range will divided to groups of specific size. - * From each group will be used only defined amount of bits. - * Syntax: range:used_size/group_size - * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769 - * The value 'N' can be used as a dynamically substituted token for the - * maximum allowed value; i.e (nmaskbits - 1). Keep in mind that it is - * dynamic, so if system changes cause the bitmap width to change, such - * as more cores in a CPU list, then any ranges using N will also change. - * - * Returns: 0 on success, -errno on invalid input strings. Error values: - * - * - ``-EINVAL``: wrong region format - * - ``-EINVAL``: invalid character in string - * - ``-ERANGE``: bit number specified too large for mask - * - ``-EOVERFLOW``: integer overflow in the input parameters - */ -int bitmap_parselist(const char *buf, unsigned long *maskp, int nmaskbits) -{ - struct region r; - long ret; - - r.nbits = nmaskbits; - bitmap_zero(maskp, r.nbits); - - while (buf) { - buf = bitmap_find_region(buf); - if (buf == NULL) - return 0; - - buf = bitmap_parse_region(buf, &r); - if (IS_ERR(buf)) - return PTR_ERR(buf); - - ret = bitmap_check_region(&r); - if (ret) - return ret; - - bitmap_set_region(&r, maskp); - } - - return 0; -} -EXPORT_SYMBOL(bitmap_parselist); - - -/** - * bitmap_parselist_user() - convert user buffer's list format ASCII - * string to bitmap - * - * @ubuf: pointer to user buffer containing string. - * @ulen: buffer size in bytes. If string is smaller than this - * then it must be terminated with a \0. - * @maskp: pointer to bitmap array that will contain result. - * @nmaskbits: size of bitmap, in bits. - * - * Wrapper for bitmap_parselist(), providing it with user buffer. - */ -int bitmap_parselist_user(const char __user *ubuf, - unsigned int ulen, unsigned long *maskp, - int nmaskbits) -{ - char *buf; - int ret; - - buf = memdup_user_nul(ubuf, ulen); - if (IS_ERR(buf)) - return PTR_ERR(buf); - - ret = bitmap_parselist(buf, maskp, nmaskbits); - - kfree(buf); - return ret; -} -EXPORT_SYMBOL(bitmap_parselist_user); - -static const char *bitmap_get_x32_reverse(const char *start, - const char *end, u32 *num) -{ - u32 ret = 0; - int c, i; - - for (i = 0; i < 32; i += 4) { - c = hex_to_bin(*end--); - if (c < 0) - return ERR_PTR(-EINVAL); - - ret |= c << i; - - if (start > end || __end_of_region(*end)) - goto out; - } - - if (hex_to_bin(*end--) >= 0) - return ERR_PTR(-EOVERFLOW); -out: - *num = ret; - return end; -} - -/** - * bitmap_parse - convert an ASCII hex string into a bitmap. - * @start: pointer to buffer containing string. - * @buflen: buffer size in bytes. If string is smaller than this - * then it must be terminated with a \0 or \n. In that case, - * UINT_MAX may be provided instead of string length. - * @maskp: pointer to bitmap array that will contain result. - * @nmaskbits: size of bitmap, in bits. - * - * Commas group hex digits into chunks. Each chunk defines exactly 32 - * bits of the resultant bitmask. No chunk may specify a value larger - * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value - * then leading 0-bits are prepended. %-EINVAL is returned for illegal - * characters. Grouping such as "1,,5", ",44", "," or "" is allowed. - * Leading, embedded and trailing whitespace accepted. - */ -int bitmap_parse(const char *start, unsigned int buflen, - unsigned long *maskp, int nmaskbits) -{ - const char *end = strnchrnul(start, buflen, '\n') - 1; - int chunks = BITS_TO_U32(nmaskbits); - u32 *bitmap = (u32 *)maskp; - int unset_bit; - int chunk; - - for (chunk = 0; ; chunk++) { - end = bitmap_find_region_reverse(start, end); - if (start > end) - break; - - if (!chunks--) - return -EOVERFLOW; - -#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN) - end = bitmap_get_x32_reverse(start, end, &bitmap[chunk ^ 1]); -#else - end = bitmap_get_x32_reverse(start, end, &bitmap[chunk]); -#endif - if (IS_ERR(end)) - return PTR_ERR(end); - } - - unset_bit = (BITS_TO_U32(nmaskbits) - chunks) * 32; - if (unset_bit < nmaskbits) { - bitmap_clear(maskp, unset_bit, nmaskbits - unset_bit); - return 0; - } - - if (find_next_bit(maskp, unset_bit, nmaskbits) != unset_bit) - return -EOVERFLOW; - - return 0; -} -EXPORT_SYMBOL(bitmap_parse); - /** * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap * @buf: pointer to a bitmap @@ -988,7 +475,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, unsigned int pos, unsigne * to @dst. * * The positions of unset bits in @old are mapped to themselves - * (the identify map). + * (the identity map). * * Apply the above specified mapping to @src, placing the result in * @dst, clearing any bits previously set in @dst. @@ -1037,7 +524,7 @@ EXPORT_SYMBOL(bitmap_remap); * the position of the m-th set bit in @new, where m == n % w. * * The positions of unset bits in @old are mapped to themselves - * (the identify map). + * (the identity map). * * Apply the above specified mapping to bit position @oldbit, returning * the new bit position. @@ -1220,169 +707,6 @@ void bitmap_fold(unsigned long *dst, const unsigned long *orig, } #endif /* CONFIG_NUMA */ -/* - * Common code for bitmap_*_region() routines. - * bitmap: array of unsigned longs corresponding to the bitmap - * pos: the beginning of the region - * order: region size (log base 2 of number of bits) - * reg_op: operation(s) to perform on that region of bitmap - * - * Can set, verify and/or release a region of bits in a bitmap, - * depending on which combination of REG_OP_* flag bits is set. - * - * A region of a bitmap is a sequence of bits in the bitmap, of - * some size '1 << order' (a power of two), aligned to that same - * '1 << order' power of two. - * - * Returns 1 if REG_OP_ISFREE succeeds (region is all zero bits). - * Returns 0 in all other cases and reg_ops. - */ - -enum { - REG_OP_ISFREE, /* true if region is all zero bits */ - REG_OP_ALLOC, /* set all bits in region */ - REG_OP_RELEASE, /* clear all bits in region */ -}; - -static int __reg_op(unsigned long *bitmap, unsigned int pos, int order, int reg_op) -{ - int nbits_reg; /* number of bits in region */ - int index; /* index first long of region in bitmap */ - int offset; /* bit offset region in bitmap[index] */ - int nlongs_reg; /* num longs spanned by region in bitmap */ - int nbitsinlong; /* num bits of region in each spanned long */ - unsigned long mask; /* bitmask for one long of region */ - int i; /* scans bitmap by longs */ - int ret = 0; /* return value */ - - /* - * Either nlongs_reg == 1 (for small orders that fit in one long) - * or (offset == 0 && mask == ~0UL) (for larger multiword orders.) - */ - nbits_reg = 1 << order; - index = pos / BITS_PER_LONG; - offset = pos - (index * BITS_PER_LONG); - nlongs_reg = BITS_TO_LONGS(nbits_reg); - nbitsinlong = min(nbits_reg, BITS_PER_LONG); - - /* - * Can't do "mask = (1UL << nbitsinlong) - 1", as that - * overflows if nbitsinlong == BITS_PER_LONG. - */ - mask = (1UL << (nbitsinlong - 1)); - mask += mask - 1; - mask <<= offset; - - switch (reg_op) { - case REG_OP_ISFREE: - for (i = 0; i < nlongs_reg; i++) { - if (bitmap[index + i] & mask) - goto done; - } - ret = 1; /* all bits in region free (zero) */ - break; - - case REG_OP_ALLOC: - for (i = 0; i < nlongs_reg; i++) - bitmap[index + i] |= mask; - break; - - case REG_OP_RELEASE: - for (i = 0; i < nlongs_reg; i++) - bitmap[index + i] &= ~mask; - break; - } -done: - return ret; -} - -/** - * bitmap_find_free_region - find a contiguous aligned mem region - * @bitmap: array of unsigned longs corresponding to the bitmap - * @bits: number of bits in the bitmap - * @order: region size (log base 2 of number of bits) to find - * - * Find a region of free (zero) bits in a @bitmap of @bits bits and - * allocate them (set them to one). Only consider regions of length - * a power (@order) of two, aligned to that power of two, which - * makes the search algorithm much faster. - * - * Return the bit offset in bitmap of the allocated region, - * or -errno on failure. - */ -int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order) -{ - unsigned int pos, end; /* scans bitmap by regions of size order */ - - for (pos = 0 ; (end = pos + (1U << order)) <= bits; pos = end) { - if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE)) - continue; - __reg_op(bitmap, pos, order, REG_OP_ALLOC); - return pos; - } - return -ENOMEM; -} -EXPORT_SYMBOL(bitmap_find_free_region); - -/** - * bitmap_release_region - release allocated bitmap region - * @bitmap: array of unsigned longs corresponding to the bitmap - * @pos: beginning of bit region to release - * @order: region size (log base 2 of number of bits) to release - * - * This is the complement to __bitmap_find_free_region() and releases - * the found region (by clearing it in the bitmap). - * - * No return value. - */ -void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order) -{ - __reg_op(bitmap, pos, order, REG_OP_RELEASE); -} -EXPORT_SYMBOL(bitmap_release_region); - -/** - * bitmap_allocate_region - allocate bitmap region - * @bitmap: array of unsigned longs corresponding to the bitmap - * @pos: beginning of bit region to allocate - * @order: region size (log base 2 of number of bits) to allocate - * - * Allocate (set bits in) a specified region of a bitmap. - * - * Return 0 on success, or %-EBUSY if specified region wasn't - * free (not all bits were zero). - */ -int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order) -{ - if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE)) - return -EBUSY; - return __reg_op(bitmap, pos, order, REG_OP_ALLOC); -} -EXPORT_SYMBOL(bitmap_allocate_region); - -/** - * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order. - * @dst: destination buffer - * @src: bitmap to copy - * @nbits: number of bits in the bitmap - * - * Require nbits % BITS_PER_LONG == 0. - */ -#ifdef __BIG_ENDIAN -void bitmap_copy_le(unsigned long *dst, const unsigned long *src, unsigned int nbits) -{ - unsigned int i; - - for (i = 0; i < nbits/BITS_PER_LONG; i++) { - if (BITS_PER_LONG == 64) - dst[i] = cpu_to_le64(src[i]); - else - dst[i] = cpu_to_le32(src[i]); - } -} -EXPORT_SYMBOL(bitmap_copy_le); -#endif - unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags) { return kmalloc_array(BITS_TO_LONGS(nbits), sizeof(unsigned long), diff --git a/lib/cpumask.c b/lib/cpumask.c index 34335c1e7265..e77ee9d46f71 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c @@ -14,7 +14,7 @@ * @start: the start point of the iteration * @wrap: assume @n crossing @start terminates the iteration * - * Returns >= nr_cpu_ids on completion + * Return: >= nr_cpu_ids on completion * * Note: the @wrap argument is required for the start condition when * we cannot assume @start is set in @mask. @@ -48,8 +48,9 @@ EXPORT_SYMBOL(cpumask_next_wrap); * @node: memory node from which to allocate or %NUMA_NO_NODE * * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is - * a nop returning a constant 1 (in ) - * Returns TRUE if memory allocation succeeded, FALSE otherwise. + * a nop returning a constant 1 (in ). + * + * Return: TRUE if memory allocation succeeded, FALSE otherwise. * * In addition, mask will be NULL if this fails. Note that gcc is * usually smart enough to know that mask can never be NULL if @@ -115,7 +116,7 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask) * @i: index number * @node: local numa_node * - * Returns online CPU according to a numa aware policy; local cpus are returned + * Return: online CPU according to a numa aware policy; local cpus are returned * first, followed by non-local ones, then it wraps around. * * For those who wants to enumerate all CPUs based on their NUMA distances, @@ -163,7 +164,7 @@ static DEFINE_PER_CPU(int, distribute_cpu_mask_prev); * Iterated calls using the same srcp1 and srcp2 will be distributed within * their intersection. * - * Returns >= nr_cpu_ids if the intersection is empty. + * Return: >= nr_cpu_ids if the intersection is empty. */ unsigned int cpumask_any_and_distribute(const struct cpumask *src1p, const struct cpumask *src2p) @@ -182,6 +183,12 @@ unsigned int cpumask_any_and_distribute(const struct cpumask *src1p, } EXPORT_SYMBOL(cpumask_any_and_distribute); +/** + * cpumask_any_distribute - Return an arbitrary cpu from srcp + * @srcp: &cpumask for selection + * + * Return: >= nr_cpu_ids if the intersection is empty. + */ unsigned int cpumask_any_distribute(const struct cpumask *srcp) { unsigned int next, prev; diff --git a/lib/fonts/Kconfig b/lib/fonts/Kconfig index c035fde66aeb..7ee468ef21ec 100644 --- a/lib/fonts/Kconfig +++ b/lib/fonts/Kconfig @@ -98,7 +98,7 @@ config FONT_10x18 config FONT_SUN8x16 bool "Sparc console 8x16 font" - depends on FRAMEBUFFER_CONSOLE && (!SPARC && FONTS || SPARC) + depends on (FRAMEBUFFER_CONSOLE && (FONTS || SPARC)) || BOOTX_TEXT help This is the high resolution console font for Sun machines. Say Y. diff --git a/lib/seq_buf.c b/lib/seq_buf.c index 45c450f423fa..010c730ca7fc 100644 --- a/lib/seq_buf.c +++ b/lib/seq_buf.c @@ -109,9 +109,7 @@ void seq_buf_do_printk(struct seq_buf *s, const char *lvl) if (s->size == 0 || s->len == 0) return; - seq_buf_terminate(s); - - start = s->buffer; + start = seq_buf_str(s); while ((lf = strchr(start, '\n'))) { int len = lf - start + 1; @@ -189,6 +187,7 @@ int seq_buf_puts(struct seq_buf *s, const char *str) seq_buf_set_overflow(s); return -1; } +EXPORT_SYMBOL_GPL(seq_buf_puts); /** * seq_buf_putc - sequence printing of simple character @@ -210,6 +209,7 @@ int seq_buf_putc(struct seq_buf *s, unsigned char c) seq_buf_set_overflow(s); return -1; } +EXPORT_SYMBOL_GPL(seq_buf_putc); /** * seq_buf_putmem - write raw data into the sequenc buffer @@ -324,23 +324,24 @@ int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc) * seq_buf_to_user - copy the sequence buffer to user space * @s: seq_buf descriptor * @ubuf: The userspace memory location to copy to + * @start: The first byte in the buffer to copy * @cnt: The amount to copy * * Copies the sequence buffer into the userspace memory pointed to - * by @ubuf. It starts from the last read position (@s->readpos) - * and writes up to @cnt characters or till it reaches the end of - * the content in the buffer (@s->len), which ever comes first. + * by @ubuf. It starts from @start and writes up to @cnt characters + * or until it reaches the end of the content in the buffer (@s->len), + * whichever comes first. * * On success, it returns a positive number of the number of bytes * it copied. * * On failure it returns -EBUSY if all of the content in the * sequence has been already read, which includes nothing in the - * sequence (@s->len == @s->readpos). + * sequence (@s->len == @start). * * Returns -EFAULT if the copy to userspace fails. */ -int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt) +int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, size_t start, int cnt) { int len; int ret; @@ -350,20 +351,17 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt) len = seq_buf_used(s); - if (len <= s->readpos) + if (len <= start) return -EBUSY; - len -= s->readpos; + len -= start; if (cnt > len) cnt = len; - ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); + ret = copy_to_user(ubuf, s->buffer + start, cnt); if (ret == cnt) return -EFAULT; - cnt -= ret; - - s->readpos += cnt; - return cnt; + return cnt - ret; } /** diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c index f2ea9f30c7c5..65f22c2578b0 100644 --- a/lib/test_bitmap.c +++ b/lib/test_bitmap.c @@ -330,6 +330,29 @@ static void __init test_copy(void) expect_eq_pbl("0-108,128-1023", bmap2, 1024); } +static void __init test_bitmap_region(void) +{ + int pos, order; + + DECLARE_BITMAP(bmap, 1000); + + bitmap_zero(bmap, 1000); + + for (order = 0; order < 10; order++) { + pos = bitmap_find_free_region(bmap, 1000, order); + if (order == 0) + expect_eq_uint(pos, 0); + else + expect_eq_uint(pos, order < 9 ? BIT(order) : -ENOMEM); + } + + bitmap_release_region(bmap, 0, 0); + for (order = 1; order < 9; order++) + bitmap_release_region(bmap, BIT(order), order); + + expect_eq_uint(bitmap_weight(bmap, 1000), 0); +} + #define EXP2_IN_BITS (sizeof(exp2) * 8) static void __init test_replace(void) @@ -1227,6 +1250,7 @@ static void __init selftest(void) test_zero_clear(); test_fill_set(); test_copy(); + test_bitmap_region(); test_replace(); test_bitmap_arr32(); test_bitmap_arr64(); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index afb88b24fa74..3e3733a7084f 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -60,7 +60,8 @@ bool no_hash_pointers __ro_after_init; EXPORT_SYMBOL_GPL(no_hash_pointers); -static noinline unsigned long long simple_strntoull(const char *startp, size_t max_chars, char **endp, unsigned int base) +noinline +static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars) { const char *cp; unsigned long long result = 0ULL; @@ -95,7 +96,7 @@ static noinline unsigned long long simple_strntoull(const char *startp, size_t m noinline unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) { - return simple_strntoull(cp, INT_MAX, endp, base); + return simple_strntoull(cp, endp, base, INT_MAX); } EXPORT_SYMBOL(simple_strtoull); @@ -130,8 +131,8 @@ long simple_strtol(const char *cp, char **endp, unsigned int base) } EXPORT_SYMBOL(simple_strtol); -static long long simple_strntoll(const char *cp, size_t max_chars, char **endp, - unsigned int base) +noinline +static long long simple_strntoll(const char *cp, char **endp, unsigned int base, size_t max_chars) { /* * simple_strntoull() safely handles receiving max_chars==0 in the @@ -140,9 +141,9 @@ static long long simple_strntoll(const char *cp, size_t max_chars, char **endp, * and the content of *cp is irrelevant. */ if (*cp == '-' && max_chars > 0) - return -simple_strntoull(cp + 1, max_chars - 1, endp, base); + return -simple_strntoull(cp + 1, endp, base, max_chars - 1); - return simple_strntoull(cp, max_chars, endp, base); + return simple_strntoull(cp, endp, base, max_chars); } /** @@ -155,7 +156,7 @@ static long long simple_strntoll(const char *cp, size_t max_chars, char **endp, */ long long simple_strtoll(const char *cp, char **endp, unsigned int base) { - return simple_strntoll(cp, INT_MAX, endp, base); + return simple_strntoll(cp, endp, base, INT_MAX); } EXPORT_SYMBOL(simple_strtoll); @@ -3648,13 +3649,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; if (is_sign) - val.s = simple_strntoll(str, - field_width >= 0 ? field_width : INT_MAX, - &next, base); + val.s = simple_strntoll(str, &next, base, + field_width >= 0 ? field_width : INT_MAX); else - val.u = simple_strntoull(str, - field_width >= 0 ? field_width : INT_MAX, - &next, base); + val.u = simple_strntoull(str, &next, base, + field_width >= 0 ? field_width : INT_MAX); switch (qualifier) { case 'H': /* that's 'hh' in format */ diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index fc3fddeb6f36..0ed6e34d6edd 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -1823,7 +1823,7 @@ static int __init iucv_init(void) rc = -EPROTONOSUPPORT; goto out; } - ctl_set_bit(0, 1); + system_ctl_set_bit(0, CR0_IUCV_BIT); rc = iucv_query_maxconn(); if (rc) goto out_ctl; @@ -1871,7 +1871,7 @@ out_dev: out_int: unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt); out_ctl: - ctl_clear_bit(0, 1); + system_ctl_clear_bit(0, 1); out: return rc; } diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index e2056c8b902c..08596c0ef070 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -8,6 +8,8 @@ */ #define _GNU_SOURCE +#define __SANE_USERSPACE_TYPES__ +#include #include #include #include @@ -51,7 +53,9 @@ static inline int landlock_restrict_self(const int ruleset_fd, #define ENV_FS_RO_NAME "LL_FS_RO" #define ENV_FS_RW_NAME "LL_FS_RW" -#define ENV_PATH_TOKEN ":" +#define ENV_TCP_BIND_NAME "LL_TCP_BIND" +#define ENV_TCP_CONNECT_NAME "LL_TCP_CONNECT" +#define ENV_DELIMITER ":" static int parse_path(char *env_path, const char ***const path_list) { @@ -60,13 +64,13 @@ static int parse_path(char *env_path, const char ***const path_list) if (env_path) { num_paths++; for (i = 0; env_path[i]; i++) { - if (env_path[i] == ENV_PATH_TOKEN[0]) + if (env_path[i] == ENV_DELIMITER[0]) num_paths++; } } *path_list = malloc(num_paths * sizeof(**path_list)); for (i = 0; i < num_paths; i++) - (*path_list)[i] = strsep(&env_path, ENV_PATH_TOKEN); + (*path_list)[i] = strsep(&env_path, ENV_DELIMITER); return num_paths; } @@ -81,8 +85,8 @@ static int parse_path(char *env_path, const char ***const path_list) /* clang-format on */ -static int populate_ruleset(const char *const env_var, const int ruleset_fd, - const __u64 allowed_access) +static int populate_ruleset_fs(const char *const env_var, const int ruleset_fd, + const __u64 allowed_access) { int num_paths, i, ret = 1; char *env_path_name; @@ -143,6 +147,39 @@ out_free_name: return ret; } +static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, + const __u64 allowed_access) +{ + int ret = 1; + char *env_port_name, *strport; + struct landlock_net_port_attr net_port = { + .allowed_access = allowed_access, + .port = 0, + }; + + env_port_name = getenv(env_var); + if (!env_port_name) + return 0; + env_port_name = strdup(env_port_name); + unsetenv(env_var); + + while ((strport = strsep(&env_port_name, ENV_DELIMITER))) { + net_port.port = atoi(strport); + if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &net_port, 0)) { + fprintf(stderr, + "Failed to update the ruleset with port \"%llu\": %s\n", + net_port.port, strerror(errno)); + goto out_free_name; + } + } + ret = 0; + +out_free_name: + free(env_port_name); + return ret; +} + /* clang-format off */ #define ACCESS_FS_ROUGHLY_READ ( \ @@ -166,39 +203,58 @@ out_free_name: /* clang-format on */ -#define LANDLOCK_ABI_LAST 3 +#define LANDLOCK_ABI_LAST 4 int main(const int argc, char *const argv[], char *const *const envp) { const char *cmd_path; char *const *cmd_argv; int ruleset_fd, abi; + char *env_port_name; __u64 access_fs_ro = ACCESS_FS_ROUGHLY_READ, access_fs_rw = ACCESS_FS_ROUGHLY_READ | ACCESS_FS_ROUGHLY_WRITE; + struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs = access_fs_rw, + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, }; if (argc < 2) { fprintf(stderr, - "usage: %s=\"...\" %s=\"...\" %s [args]...\n\n", - ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]); + "usage: %s=\"...\" %s=\"...\" %s=\"...\" %s=\"...\"%s " + " [args]...\n\n", + ENV_FS_RO_NAME, ENV_FS_RW_NAME, ENV_TCP_BIND_NAME, + ENV_TCP_CONNECT_NAME, argv[0]); fprintf(stderr, "Launch a command in a restricted environment.\n\n"); - fprintf(stderr, "Environment variables containing paths, " - "each separated by a colon:\n"); + fprintf(stderr, + "Environment variables containing paths and ports " + "each separated by a colon:\n"); fprintf(stderr, "* %s: list of paths allowed to be used in a read-only way.\n", ENV_FS_RO_NAME); fprintf(stderr, - "* %s: list of paths allowed to be used in a read-write way.\n", + "* %s: list of paths allowed to be used in a read-write way.\n\n", ENV_FS_RW_NAME); + fprintf(stderr, + "Environment variables containing ports are optional " + "and could be skipped.\n"); + fprintf(stderr, + "* %s: list of ports allowed to bind (server).\n", + ENV_TCP_BIND_NAME); + fprintf(stderr, + "* %s: list of ports allowed to connect (client).\n", + ENV_TCP_CONNECT_NAME); fprintf(stderr, "\nexample:\n" "%s=\"/bin:/lib:/usr:/proc:/etc:/dev/urandom\" " "%s=\"/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp\" " + "%s=\"9418\" " + "%s=\"80:443\" " "%s bash -i\n\n", - ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]); + ENV_FS_RO_NAME, ENV_FS_RW_NAME, ENV_TCP_BIND_NAME, + ENV_TCP_CONNECT_NAME, argv[0]); fprintf(stderr, "This sandboxer can use Landlock features " "up to ABI version %d.\n", @@ -255,7 +311,12 @@ int main(const int argc, char *const argv[], char *const *const envp) case 2: /* Removes LANDLOCK_ACCESS_FS_TRUNCATE for ABI < 3 */ ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE; - + __attribute__((fallthrough)); + case 3: + /* Removes network support for ABI < 4 */ + ruleset_attr.handled_access_net &= + ~(LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP); fprintf(stderr, "Hint: You should update the running kernel " "to leverage Landlock features " @@ -274,18 +335,42 @@ int main(const int argc, char *const argv[], char *const *const envp) access_fs_ro &= ruleset_attr.handled_access_fs; access_fs_rw &= ruleset_attr.handled_access_fs; + /* Removes bind access attribute if not supported by a user. */ + env_port_name = getenv(ENV_TCP_BIND_NAME); + if (!env_port_name) { + ruleset_attr.handled_access_net &= + ~LANDLOCK_ACCESS_NET_BIND_TCP; + } + /* Removes connect access attribute if not supported by a user. */ + env_port_name = getenv(ENV_TCP_CONNECT_NAME); + if (!env_port_name) { + ruleset_attr.handled_access_net &= + ~LANDLOCK_ACCESS_NET_CONNECT_TCP; + } + ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); if (ruleset_fd < 0) { perror("Failed to create a ruleset"); return 1; } - if (populate_ruleset(ENV_FS_RO_NAME, ruleset_fd, access_fs_ro)) { + + if (populate_ruleset_fs(ENV_FS_RO_NAME, ruleset_fd, access_fs_ro)) { goto err_close_ruleset; } - if (populate_ruleset(ENV_FS_RW_NAME, ruleset_fd, access_fs_rw)) { + if (populate_ruleset_fs(ENV_FS_RW_NAME, ruleset_fd, access_fs_rw)) { goto err_close_ruleset; } + + if (populate_ruleset_net(ENV_TCP_BIND_NAME, ruleset_fd, + LANDLOCK_ACCESS_NET_BIND_TCP)) { + goto err_close_ruleset; + } + if (populate_ruleset_net(ENV_TCP_CONNECT_NAME, ruleset_fd, + LANDLOCK_ACCESS_NET_CONNECT_TCP)) { + goto err_close_ruleset; + } + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { perror("Failed to restrict privileges"); goto err_close_ruleset; diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py index a84cc5737c2c..180952fb91c1 100755 --- a/scripts/clang-tools/gen_compile_commands.py +++ b/scripts/clang-tools/gen_compile_commands.py @@ -19,7 +19,7 @@ _DEFAULT_OUTPUT = 'compile_commands.json' _DEFAULT_LOG_LEVEL = 'WARNING' _FILENAME_PATTERN = r'^\..*\.cmd$' -_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.[cS]) *(;|$)' +_LINE_PATTERN = r'^(saved)?cmd_[^ ]*\.o := (?P.* )(?P[^ ]*\.[cS]) *(;|$)' _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] # The tools/ directory adopts a different build system, and produces .cmd # files in a different format. Do not support it. @@ -213,15 +213,15 @@ def main(): result = line_matcher.match(f.readline()) if result: try: - entry = process_line(directory, result.group(1), - result.group(2)) + entry = process_line(directory, result.group('command_prefix'), + result.group('file_path')) compile_commands.append(entry) except ValueError as err: logging.info('Could not add line from %s: %s', cmdfile, err) with open(output, 'wt') as f: - json.dump(compile_commands, f, indent=2, sort_keys=True) + json.dump(sorted(compile_commands, key=lambda x: x["file"]), f, indent=2, sort_keys=True) if __name__ == '__main__': diff --git a/scripts/clang-tools/run-clang-tools.py b/scripts/clang-tools/run-clang-tools.py index 3266708a8658..f31ffd09e1ea 100755 --- a/scripts/clang-tools/run-clang-tools.py +++ b/scripts/clang-tools/run-clang-tools.py @@ -33,6 +33,11 @@ def parse_arguments(): path_help = "Path to the compilation database to parse" parser.add_argument("path", type=str, help=path_help) + checks_help = "Checks to pass to the analysis" + parser.add_argument("-checks", type=str, default=None, help=checks_help) + header_filter_help = "Pass the -header-filter value to the tool" + parser.add_argument("-header-filter", type=str, default=None, help=header_filter_help) + return parser.parse_args() @@ -45,14 +50,27 @@ def init(l, a): def run_analysis(entry): # Disable all checks, then re-enable the ones we want - checks = [] - checks.append("-checks=-*") - if args.type == "clang-tidy": - checks.append("linuxkernel-*") + global args + checks = None + if args.checks: + checks = args.checks.split(',') else: - checks.append("clang-analyzer-*") - checks.append("-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling") - p = subprocess.run(["clang-tidy", "-p", args.path, ",".join(checks), entry["file"]], + checks = ["-*"] + if args.type == "clang-tidy": + checks.append("linuxkernel-*") + else: + checks.append("clang-analyzer-*") + checks.append("-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling") + file = entry["file"] + if not file.endswith(".c") and not file.endswith(".cpp"): + with lock: + print(f"Skipping non-C file: '{file}'", file=sys.stderr) + return + pargs = ["clang-tidy", "-p", args.path, "-checks=" + ",".join(checks)] + if args.header_filter: + pargs.append("-header-filter=" + args.header_filter) + pargs.append(file) + p = subprocess.run(pargs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=entry["directory"]) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 53a0070ff5df..38650e52ef57 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -423,7 +423,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, /* high level check about policy management - fine grained in * below after unpack */ - error = aa_may_manage_policy(label, ns, mask); + error = aa_may_manage_policy(current_cred(), label, ns, mask); if (error) goto end_section; @@ -486,7 +486,8 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, /* high level check about policy management - fine grained in * below after unpack */ - error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY); + error = aa_may_manage_policy(current_cred(), label, ns, + AA_MAY_REMOVE_POLICY); if (error) goto out; @@ -618,23 +619,23 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, if (profile_unconfined(profile)) return; - if (rules->file.dfa && *match_str == AA_CLASS_FILE) { - state = aa_dfa_match_len(rules->file.dfa, - rules->file.start[AA_CLASS_FILE], + if (rules->file->dfa && *match_str == AA_CLASS_FILE) { + state = aa_dfa_match_len(rules->file->dfa, + rules->file->start[AA_CLASS_FILE], match_str + 1, match_len - 1); if (state) { struct path_cond cond = { }; - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); } - } else if (rules->policy.dfa) { + } else if (rules->policy->dfa) { if (!RULE_MEDIATES(rules, *match_str)) return; /* no change to current perms */ - state = aa_dfa_match_len(rules->policy.dfa, - rules->policy.start[0], + state = aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], match_str, match_len); if (state) - tmp = *aa_lookup_perms(&rules->policy, state); + tmp = *aa_lookup_perms(rules->policy, state); } aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum_raw(perms, &tmp); @@ -1095,7 +1096,7 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v) struct aa_profile *profile = labels_profile(label); if (profile->attach.xmatch_str) seq_printf(seq, "%s\n", profile->attach.xmatch_str); - else if (profile->attach.xmatch.dfa) + else if (profile->attach.xmatch->dfa) seq_puts(seq, "\n"); else seq_printf(seq, "%s\n", profile->base.name); @@ -1314,7 +1315,6 @@ SEQ_RAWDATA_FOPS(compressed_size); static int decompress_zstd(char *src, size_t slen, char *dst, size_t dlen) { -#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY if (slen < dlen) { const size_t wksp_len = zstd_dctx_workspace_bound(); zstd_dctx *ctx; @@ -1341,7 +1341,6 @@ cleanup: kvfree(wksp); return ret; } -#endif if (dlen < slen) return -EINVAL; @@ -1806,7 +1805,8 @@ static int ns_mkdir_op(struct mnt_idmap *idmap, struct inode *dir, int error; label = begin_current_label_crit_section(); - error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); + error = aa_may_manage_policy(current_cred(), label, NULL, + AA_MAY_LOAD_POLICY); end_current_label_crit_section(label); if (error) return error; @@ -1855,7 +1855,8 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) int error; label = begin_current_label_crit_section(); - error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); + error = aa_may_manage_policy(current_cred(), label, NULL, + AA_MAY_LOAD_POLICY); end_current_label_crit_section(label); if (error) return error; @@ -2339,10 +2340,16 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = { AA_SFS_FILE_BOOLEAN("post_nnp_subset", 1), AA_SFS_FILE_BOOLEAN("computed_longest_left", 1), AA_SFS_DIR("attach_conditions", aa_sfs_entry_attach), + AA_SFS_FILE_BOOLEAN("disconnected.path", 1), AA_SFS_FILE_STRING("version", "1.2"), { } }; +static struct aa_sfs_entry aa_sfs_entry_unconfined[] = { + AA_SFS_FILE_BOOLEAN("change_profile", 1), + { } +}; + static struct aa_sfs_entry aa_sfs_entry_versions[] = { AA_SFS_FILE_BOOLEAN("v5", 1), AA_SFS_FILE_BOOLEAN("v6", 1), @@ -2352,11 +2359,15 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = { { } }; +#define PERMS32STR "allow deny subtree cond kill complain prompt audit quiet hide xindex tag label" static struct aa_sfs_entry aa_sfs_entry_policy[] = { AA_SFS_DIR("versions", aa_sfs_entry_versions), AA_SFS_FILE_BOOLEAN("set_load", 1), /* number of out of band transitions supported */ AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED), + AA_SFS_FILE_U64("permstable32_version", 1), + AA_SFS_FILE_STRING("permstable32", PERMS32STR), + AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined), { } }; @@ -2368,6 +2379,7 @@ static struct aa_sfs_entry aa_sfs_entry_mount[] = { static struct aa_sfs_entry aa_sfs_entry_ns[] = { AA_SFS_FILE_BOOLEAN("profile", 1), AA_SFS_FILE_BOOLEAN("pivot_root", 0), + AA_SFS_FILE_STRING("mask", "userns_create"), { } }; @@ -2382,6 +2394,12 @@ static struct aa_sfs_entry aa_sfs_entry_query[] = { AA_SFS_DIR("label", aa_sfs_entry_query_label), { } }; + +static struct aa_sfs_entry aa_sfs_entry_io_uring[] = { + AA_SFS_FILE_STRING("mask", "sqpoll override_creds"), + { } +}; + static struct aa_sfs_entry aa_sfs_entry_features[] = { AA_SFS_DIR("policy", aa_sfs_entry_policy), AA_SFS_DIR("domain", aa_sfs_entry_domain), @@ -2395,6 +2413,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), AA_SFS_DIR("signal", aa_sfs_entry_signal), AA_SFS_DIR("query", aa_sfs_entry_query), + AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring), { } }; diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 5a7978aa4b19..45beb1c5f747 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -58,8 +58,8 @@ static const char *const aa_class_names[] = { "io_uring", "module", "lsm", - "unknown", - "unknown", + "namespace", + "io_uring", "unknown", "unknown", "unknown", @@ -85,37 +85,36 @@ static const char *const aa_class_names[] = { /** * audit_pre() - core AppArmor function. * @ab: audit buffer to fill (NOT NULL) - * @ca: audit structure containing data to audit (NOT NULL) + * @va: audit structure containing data to audit (NOT NULL) * - * Record common AppArmor audit data from @sa + * Record common AppArmor audit data from @va */ -static void audit_pre(struct audit_buffer *ab, void *ca) +static void audit_pre(struct audit_buffer *ab, void *va) { - struct common_audit_data *sa = ca; + struct apparmor_audit_data *ad = aad_of_va(va); if (aa_g_audit_header) { audit_log_format(ab, "apparmor=\"%s\"", - aa_audit_type[aad(sa)->type]); + aa_audit_type[ad->type]); } - if (aad(sa)->op) { - audit_log_format(ab, " operation=\"%s\"", aad(sa)->op); - } + if (ad->op) + audit_log_format(ab, " operation=\"%s\"", ad->op); - if (aad(sa)->class) + if (ad->class) audit_log_format(ab, " class=\"%s\"", - aad(sa)->class <= AA_CLASS_LAST ? - aa_class_names[aad(sa)->class] : + ad->class <= AA_CLASS_LAST ? + aa_class_names[ad->class] : "unknown"); - if (aad(sa)->info) { - audit_log_format(ab, " info=\"%s\"", aad(sa)->info); - if (aad(sa)->error) - audit_log_format(ab, " error=%d", aad(sa)->error); + if (ad->info) { + audit_log_format(ab, " info=\"%s\"", ad->info); + if (ad->error) + audit_log_format(ab, " error=%d", ad->error); } - if (aad(sa)->label) { - struct aa_label *label = aad(sa)->label; + if (ad->subj_label) { + struct aa_label *label = ad->subj_label; if (label_isprofile(label)) { struct aa_profile *profile = labels_profile(label); @@ -134,42 +133,44 @@ static void audit_pre(struct audit_buffer *ab, void *ca) } } - if (aad(sa)->name) { + if (ad->name) { audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, aad(sa)->name); + audit_log_untrustedstring(ab, ad->name); } } /** * aa_audit_msg - Log a message to the audit subsystem - * @sa: audit event structure (NOT NULL) + * @type: audit type for the message + * @ad: audit event structure (NOT NULL) * @cb: optional callback fn for type specific fields (MAYBE NULL) */ -void aa_audit_msg(int type, struct common_audit_data *sa, +void aa_audit_msg(int type, struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)) { - aad(sa)->type = type; - common_lsm_audit(sa, audit_pre, cb); + ad->type = type; + common_lsm_audit(&ad->common, audit_pre, cb); } /** * aa_audit - Log a profile based audit event to the audit subsystem * @type: audit type for the message * @profile: profile to check against (NOT NULL) - * @sa: audit event (NOT NULL) + * @ad: audit event (NOT NULL) * @cb: optional callback fn for type specific fields (MAYBE NULL) * * Handle default message switching based off of audit mode flags * * Returns: error on failure */ -int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, +int aa_audit(int type, struct aa_profile *profile, + struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)) { AA_BUG(!profile); if (type == AUDIT_APPARMOR_AUTO) { - if (likely(!aad(sa)->error)) { + if (likely(!ad->error)) { if (AUDIT_MODE(profile) != AUDIT_ALL) return 0; type = AUDIT_APPARMOR_AUDIT; @@ -181,24 +182,24 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, if (AUDIT_MODE(profile) == AUDIT_QUIET || (type == AUDIT_APPARMOR_DENIED && AUDIT_MODE(profile) == AUDIT_QUIET_DENIED)) - return aad(sa)->error; + return ad->error; if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; - aad(sa)->label = &profile->label; + ad->subj_label = &profile->label; - aa_audit_msg(type, sa, cb); + aa_audit_msg(type, ad, cb); - if (aad(sa)->type == AUDIT_APPARMOR_KILL) + if (ad->type == AUDIT_APPARMOR_KILL) (void)send_sig_info(SIGKILL, NULL, - sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ? - sa->u.tsk : current); + ad->common.type == LSM_AUDIT_DATA_TASK && + ad->common.u.tsk ? ad->common.u.tsk : current); - if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED) - return complain_error(aad(sa)->error); + if (ad->type == AUDIT_APPARMOR_ALLOWED) + return complain_error(ad->error); - return aad(sa)->error; + return ad->error; } struct aa_audit_rule { diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c index 326a51838ef2..9934df16c843 100644 --- a/security/apparmor/capability.c +++ b/security/apparmor/capability.c @@ -38,8 +38,8 @@ static DEFINE_PER_CPU(struct audit_cache, audit_cache); /** * audit_cb - call back for capability components of audit struct - * @ab - audit buffer (NOT NULL) - * @va - audit struct to audit data from (NOT NULL) + * @ab: audit buffer (NOT NULL) + * @va: audit struct to audit data from (NOT NULL) */ static void audit_cb(struct audit_buffer *ab, void *va) { @@ -51,7 +51,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) /** * audit_caps - audit a capability - * @sa: audit data + * @ad: audit data * @profile: profile being tested for confinement (NOT NULL) * @cap: capability tested * @error: error code returned by test @@ -59,9 +59,9 @@ static void audit_cb(struct audit_buffer *ab, void *va) * Do auditing of capability and handle, audit/complain/kill modes switching * and duplicate message elimination. * - * Returns: 0 or sa->error on success, error code on failure + * Returns: 0 or ad->error on success, error code on failure */ -static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, +static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile, int cap, int error) { struct aa_ruleset *rules = list_first_entry(&profile->rules, @@ -69,7 +69,7 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, struct audit_cache *ent; int type = AUDIT_APPARMOR_AUTO; - aad(sa)->error = error; + ad->error = error; if (likely(!error)) { /* test if auditing is being forced */ @@ -101,7 +101,7 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, } put_cpu_var(audit_cache); - return aa_audit(type, profile, sa, audit_cb); + return aa_audit(type, profile, ad, audit_cb); } /** @@ -109,12 +109,12 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, * @profile: profile being enforced (NOT NULL, NOT unconfined) * @cap: capability to test if allowed * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated - * @sa: audit data (MAY BE NULL indicating no auditing) + * @ad: audit data (MAY BE NULL indicating no auditing) * * Returns: 0 if allowed else -EPERM */ static int profile_capable(struct aa_profile *profile, int cap, - unsigned int opts, struct common_audit_data *sa) + unsigned int opts, struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); @@ -132,14 +132,15 @@ static int profile_capable(struct aa_profile *profile, int cap, /* audit the cap request in complain mode but note that it * should be optional. */ - aad(sa)->info = "optional: no audit"; + ad->info = "optional: no audit"; } - return audit_caps(sa, profile, cap, error); + return audit_caps(ad, profile, cap, error); } /** * aa_capable - test permission to use capability + * @subj_cred: cred we are testing capability against * @label: label being tested for capability (NOT NULL) * @cap: capability to be tested * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated @@ -148,15 +149,17 @@ static int profile_capable(struct aa_profile *profile, int cap, * * Returns: 0 on success, or else an error code. */ -int aa_capable(struct aa_label *label, int cap, unsigned int opts) +int aa_capable(const struct cred *subj_cred, struct aa_label *label, + int cap, unsigned int opts) { struct aa_profile *profile; int error = 0; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE); - sa.u.cap = cap; + ad.subj_cred = subj_cred; + ad.common.u.cap = cap; error = fn_for_each_confined(label, profile, - profile_capable(profile, cap, opts, &sa)); + profile_capable(profile, cap, opts, &ad)); return error; } diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index f3715cda59c5..89fbeab4b33b 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -31,6 +31,7 @@ /** * may_change_ptraced_domain - check if can change profile on ptraced task + * @to_cred: cred of task changing domain * @to_label: profile to change to (NOT NULL) * @info: message if there is an error * @@ -39,28 +40,34 @@ * * Returns: %0 or error if change not allowed */ -static int may_change_ptraced_domain(struct aa_label *to_label, +static int may_change_ptraced_domain(const struct cred *to_cred, + struct aa_label *to_label, const char **info) { struct task_struct *tracer; struct aa_label *tracerl = NULL; + const struct cred *tracer_cred = NULL; + int error = 0; rcu_read_lock(); tracer = ptrace_parent(current); - if (tracer) + if (tracer) { /* released below */ tracerl = aa_get_task_label(tracer); - + tracer_cred = get_task_cred(tracer); + } /* not ptraced */ if (!tracer || unconfined(tracerl)) goto out; - error = aa_may_ptrace(tracerl, to_label, PTRACE_MODE_ATTACH); + error = aa_may_ptrace(tracer_cred, tracerl, to_cred, to_label, + PTRACE_MODE_ATTACH); out: rcu_read_unlock(); aa_put_label(tracerl); + put_cred(tracer_cred); if (error) *info = "ptrace prevents transition"; @@ -70,7 +77,7 @@ out: /**** TODO: dedup to aa_label_match - needs perm and dfa, merging * specifically this is an exact copy of aa_label_match except * aa_compute_perms is replaced with aa_compute_fperms - * and policy.dfa with file.dfa + * and policy->dfa with file->dfa ****/ /* match a profile and its associated ns component if needed * Assumes visibility test has already been done. @@ -86,16 +93,16 @@ static inline aa_state_t match_component(struct aa_profile *profile, const char *ns_name; if (stack) - state = aa_dfa_match(rules->file.dfa, state, "&"); + state = aa_dfa_match(rules->file->dfa, state, "&"); if (profile->ns == tp->ns) - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); /* try matching with namespace name and then profile */ ns_name = aa_ns_name(profile->ns, tp->ns, true); - state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); - state = aa_dfa_match(rules->file.dfa, state, ns_name); - state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); - return aa_dfa_match(rules->file.dfa, state, tp->base.hname); + state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); + state = aa_dfa_match(rules->file->dfa, state, ns_name); + state = aa_dfa_match_len(rules->file->dfa, state, ":", 1); + return aa_dfa_match(rules->file->dfa, state, tp->base.hname); } /** @@ -143,12 +150,12 @@ next: label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) continue; - state = aa_dfa_match(rules->file.dfa, state, "//&"); + state = aa_dfa_match(rules->file->dfa, state, "//&"); state = match_component(profile, tp, false, state); if (!state) goto fail; } - *perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); + *perms = *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, perms); if ((perms->allow & request) != request) return -EACCES; @@ -203,7 +210,7 @@ static int label_components_match(struct aa_profile *profile, return 0; next: - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); label_for_each_cont(i, label, tp) { @@ -212,7 +219,7 @@ next: state = match_component(profile, tp, stack, start); if (!state) goto fail; - tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); + tmp = *(aa_lookup_fperms(rules->file, state, &cond)); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); } @@ -265,6 +272,7 @@ static int label_match(struct aa_profile *profile, struct aa_label *label, * @stack: whether this is a stacking request * @request: requested perms * @start: state to start matching in + * @perms: Returns computed perms (NOT NULL) * * * Returns: permission set @@ -309,7 +317,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, might_sleep(); /* transition from exec match to xattr set */ - state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); + state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); d = bprm->file->f_path.dentry; for (i = 0; i < attach->xattr_count; i++) { @@ -323,20 +331,20 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, * that not present xattr can be distinguished from a 0 * length value or rule that matches any value */ - state = aa_dfa_null_transition(attach->xmatch.dfa, + state = aa_dfa_null_transition(attach->xmatch->dfa, state); /* Check xattr value */ - state = aa_dfa_match_len(attach->xmatch.dfa, state, + state = aa_dfa_match_len(attach->xmatch->dfa, state, value, size); - index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; - perm = attach->xmatch.perms[index].allow; + index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; + perm = attach->xmatch->perms[index].allow; if (!(perm & MAY_EXEC)) { ret = -EINVAL; goto out; } } /* transition to next element */ - state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); + state = aa_dfa_outofband_transition(attach->xmatch->dfa, state); if (size < 0) { /* * No xattr match, so verify if transition to @@ -359,11 +367,11 @@ out: /** * find_attach - do attachment search for unconfined processes - * @bprm - binprm structure of transitioning task + * @bprm: binprm structure of transitioning task * @ns: the current namespace (NOT NULL) - * @head - profile list to walk (NOT NULL) - * @name - to match against (NOT NULL) - * @info - info message if there was an error (NOT NULL) + * @head: profile list to walk (NOT NULL) + * @name: to match against (NOT NULL) + * @info: info message if there was an error (NOT NULL) * * Do a linear search on the profiles in the list. There is a matching * preference where an exact match is preferred over a name which uses @@ -405,16 +413,16 @@ restart: * as another profile, signal a conflict and refuse to * match. */ - if (attach->xmatch.dfa) { + if (attach->xmatch->dfa) { unsigned int count; aa_state_t state; u32 index, perm; - state = aa_dfa_leftmatch(attach->xmatch.dfa, - attach->xmatch.start[AA_CLASS_XMATCH], + state = aa_dfa_leftmatch(attach->xmatch->dfa, + attach->xmatch->start[AA_CLASS_XMATCH], name, &count); - index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; - perm = attach->xmatch.perms[index].allow; + index = ACCEPT_TABLE(attach->xmatch->dfa)[state]; + perm = attach->xmatch->perms[index].allow; /* any accepting state means a valid match. */ if (perm & MAY_EXEC) { int ret = 0; @@ -517,7 +525,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, /* TODO: move lookup parsing to unpack time so this is a straight * index into the resultant label */ - for (*name = rules->file.trans.table[index]; !label && *name; + for (*name = rules->file->trans.table[index]; !label && *name; *name = next_name(xtype, *name)) { if (xindex & AA_X_CHILD) { struct aa_profile *new_profile; @@ -545,6 +553,7 @@ struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, * @name: name to lookup (NOT NULL) * @xindex: index into x transition table * @lookupname: returns: name used in lookup if one was specified (NOT NULL) + * @info: info message if there was an error (NOT NULL) * * find label for a transition index * @@ -570,7 +579,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile, break; case AA_X_TABLE: /* TODO: fix when perm mapping done at unload */ - stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; + stack = rules->file->trans.table[xindex & AA_X_INDEX_MASK]; if (*stack != '&') { /* released by caller */ new = x_table_lookup(profile, xindex, lookupname); @@ -619,7 +628,8 @@ static struct aa_label *x_to_label(struct aa_profile *profile, return new; } -static struct aa_label *profile_transition(struct aa_profile *profile, +static struct aa_label *profile_transition(const struct cred *subj_cred, + struct aa_profile *profile, const struct linux_binprm *bprm, char *buffer, struct path_cond *cond, bool *secure_exec) @@ -628,7 +638,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile, typeof(*rules), list); struct aa_label *new = NULL; const char *info = NULL, *name = NULL, *target = NULL; - aa_state_t state = rules->file.start[AA_CLASS_FILE]; + aa_state_t state = rules->file->start[AA_CLASS_FILE]; struct aa_perms perms = {}; bool nonewprivs = false; int error = 0; @@ -662,7 +672,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile, } /* find exec permissions for name */ - state = aa_str_perms(&(rules->file), state, name, cond, &perms); + state = aa_str_perms(rules->file, state, name, cond, &perms); if (perms.allow & MAY_EXEC) { /* exec permission determine how to transition */ new = x_to_label(profile, bprm, name, perms.xindex, &target, @@ -709,7 +719,8 @@ static struct aa_label *profile_transition(struct aa_profile *profile, } audit: - aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, target, new, + aa_audit_file(subj_cred, profile, &perms, OP_EXEC, MAY_EXEC, name, + target, new, cond->uid, info, error); if (!new || nonewprivs) { aa_put_label(new); @@ -719,14 +730,15 @@ audit: return new; } -static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, +static int profile_onexec(const struct cred *subj_cred, + struct aa_profile *profile, struct aa_label *onexec, bool stack, const struct linux_binprm *bprm, char *buffer, struct path_cond *cond, bool *secure_exec) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); - aa_state_t state = rules->file.start[AA_CLASS_FILE]; + aa_state_t state = rules->file->start[AA_CLASS_FILE]; struct aa_perms perms = {}; const char *xname = NULL, *info = "change_profile onexec"; int error = -EACCES; @@ -759,7 +771,7 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, } /* find exec permissions for name */ - state = aa_str_perms(&(rules->file), state, xname, cond, &perms); + state = aa_str_perms(rules->file, state, xname, cond, &perms); if (!(perms.allow & AA_MAY_ONEXEC)) { info = "no change_onexec valid for executable"; goto audit; @@ -768,7 +780,7 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, * onexec permission is linked to exec with a standard pairing * exec\0change_profile */ - state = aa_dfa_null_transition(rules->file.dfa, state); + state = aa_dfa_null_transition(rules->file->dfa, state); error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, state, &perms); if (error) { @@ -787,13 +799,15 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, } audit: - return aa_audit_file(profile, &perms, OP_EXEC, AA_MAY_ONEXEC, xname, + return aa_audit_file(subj_cred, profile, &perms, OP_EXEC, + AA_MAY_ONEXEC, xname, NULL, onexec, cond->uid, info, error); } /* ensure none ns domain transitions are correctly applied with onexec */ -static struct aa_label *handle_onexec(struct aa_label *label, +static struct aa_label *handle_onexec(const struct cred *subj_cred, + struct aa_label *label, struct aa_label *onexec, bool stack, const struct linux_binprm *bprm, char *buffer, struct path_cond *cond, @@ -810,26 +824,28 @@ static struct aa_label *handle_onexec(struct aa_label *label, if (!stack) { error = fn_for_each_in_ns(label, profile, - profile_onexec(profile, onexec, stack, + profile_onexec(subj_cred, profile, onexec, stack, bprm, buffer, cond, unsafe)); if (error) return ERR_PTR(error); new = fn_label_build_in_ns(label, profile, GFP_KERNEL, aa_get_newest_label(onexec), - profile_transition(profile, bprm, buffer, + profile_transition(subj_cred, profile, bprm, + buffer, cond, unsafe)); } else { /* TODO: determine how much we want to loosen this */ error = fn_for_each_in_ns(label, profile, - profile_onexec(profile, onexec, stack, bprm, + profile_onexec(subj_cred, profile, onexec, stack, bprm, buffer, cond, unsafe)); if (error) return ERR_PTR(error); new = fn_label_build_in_ns(label, profile, GFP_KERNEL, aa_label_merge(&profile->label, onexec, GFP_KERNEL), - profile_transition(profile, bprm, buffer, + profile_transition(subj_cred, profile, bprm, + buffer, cond, unsafe)); } @@ -838,7 +854,8 @@ static struct aa_label *handle_onexec(struct aa_label *label, /* TODO: get rid of GLOBAL_ROOT_UID */ error = fn_for_each_in_ns(label, profile, - aa_audit_file(profile, &nullperms, OP_CHANGE_ONEXEC, + aa_audit_file(subj_cred, profile, &nullperms, + OP_CHANGE_ONEXEC, AA_MAY_ONEXEC, bprm->filename, NULL, onexec, GLOBAL_ROOT_UID, "failed to build target label", -ENOMEM)); @@ -857,6 +874,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) { struct aa_task_ctx *ctx; struct aa_label *label, *new = NULL; + const struct cred *subj_cred; struct aa_profile *profile; char *buffer = NULL; const char *info = NULL; @@ -869,6 +887,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) file_inode(bprm->file)->i_mode }; + subj_cred = current_cred(); ctx = task_ctx(current); AA_BUG(!cred_label(bprm->cred)); AA_BUG(!ctx); @@ -895,11 +914,12 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) /* Test for onexec first as onexec override other x transitions. */ if (ctx->onexec) - new = handle_onexec(label, ctx->onexec, ctx->token, + new = handle_onexec(subj_cred, label, ctx->onexec, ctx->token, bprm, buffer, &cond, &unsafe); else new = fn_label_build(label, profile, GFP_KERNEL, - profile_transition(profile, bprm, buffer, + profile_transition(subj_cred, profile, bprm, + buffer, &cond, &unsafe)); AA_BUG(!new); @@ -934,7 +954,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) { /* TODO: test needs to be profile of label to new */ - error = may_change_ptraced_domain(new, &info); + error = may_change_ptraced_domain(bprm->cred, new, &info); if (error) goto audit; } @@ -971,7 +991,8 @@ done: audit: error = fn_for_each(label, profile, - aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, + aa_audit_file(current_cred(), profile, &nullperms, + OP_EXEC, MAY_EXEC, bprm->filename, NULL, new, vfsuid_into_kuid(vfsuid), info, error)); aa_put_label(new); @@ -987,7 +1008,8 @@ audit: * * Returns: label for hat transition OR ERR_PTR. Does NOT return NULL */ -static struct aa_label *build_change_hat(struct aa_profile *profile, +static struct aa_label *build_change_hat(const struct cred *subj_cred, + struct aa_profile *profile, const char *name, bool sibling) { struct aa_profile *root, *hat = NULL; @@ -1019,7 +1041,8 @@ static struct aa_label *build_change_hat(struct aa_profile *profile, aa_put_profile(root); audit: - aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT, + aa_audit_file(subj_cred, profile, &nullperms, OP_CHANGE_HAT, + AA_MAY_CHANGEHAT, name, hat ? hat->base.hname : NULL, hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info, error); @@ -1035,7 +1058,8 @@ audit: * * Returns: label for hat transition or ERR_PTR. Does not return NULL */ -static struct aa_label *change_hat(struct aa_label *label, const char *hats[], +static struct aa_label *change_hat(const struct cred *subj_cred, + struct aa_label *label, const char *hats[], int count, int flags) { struct aa_profile *profile, *root, *hat = NULL; @@ -1111,7 +1135,8 @@ fail: */ /* TODO: get rid of GLOBAL_ROOT_UID */ if (count > 1 || COMPLAIN_MODE(profile)) { - aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, + aa_audit_file(subj_cred, profile, &nullperms, + OP_CHANGE_HAT, AA_MAY_CHANGEHAT, name, NULL, NULL, GLOBAL_ROOT_UID, info, error); } @@ -1120,7 +1145,8 @@ fail: build: new = fn_label_build_in_ns(label, profile, GFP_KERNEL, - build_change_hat(profile, name, sibling), + build_change_hat(subj_cred, profile, name, + sibling), aa_get_label(&profile->label)); if (!new) { info = "label build failed"; @@ -1150,7 +1176,7 @@ build: */ int aa_change_hat(const char *hats[], int count, u64 token, int flags) { - const struct cred *cred; + const struct cred *subj_cred; struct aa_task_ctx *ctx = task_ctx(current); struct aa_label *label, *previous, *new = NULL, *target = NULL; struct aa_profile *profile; @@ -1159,8 +1185,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) int error = 0; /* released below */ - cred = get_current_cred(); - label = aa_get_newest_cred_label(cred); + subj_cred = get_current_cred(); + label = aa_get_newest_cred_label(subj_cred); previous = aa_get_newest_label(ctx->previous); /* @@ -1180,7 +1206,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) } if (count) { - new = change_hat(label, hats, count, flags); + new = change_hat(subj_cred, label, hats, count, flags); AA_BUG(!new); if (IS_ERR(new)) { error = PTR_ERR(new); @@ -1189,7 +1215,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) goto out; } - error = may_change_ptraced_domain(new, &info); + /* target cred is the same as current except new label */ + error = may_change_ptraced_domain(subj_cred, new, &info); if (error) goto fail; @@ -1242,7 +1269,7 @@ out: aa_put_label(new); aa_put_label(previous); aa_put_label(label); - put_cred(cred); + put_cred(subj_cred); return error; @@ -1252,7 +1279,7 @@ kill: fail: fn_for_each_in_ns(label, profile, - aa_audit_file(profile, &perms, OP_CHANGE_HAT, + aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL, NULL, target, GLOBAL_ROOT_UID, info, error)); @@ -1261,6 +1288,7 @@ fail: static int change_profile_perms_wrapper(const char *op, const char *name, + const struct cred *subj_cred, struct aa_profile *profile, struct aa_label *target, bool stack, u32 request, struct aa_perms *perms) @@ -1272,16 +1300,19 @@ static int change_profile_perms_wrapper(const char *op, const char *name, if (!error) error = change_profile_perms(profile, target, stack, request, - rules->file.start[AA_CLASS_FILE], + rules->file->start[AA_CLASS_FILE], perms); if (error) - error = aa_audit_file(profile, perms, op, request, name, + error = aa_audit_file(subj_cred, profile, perms, op, request, + name, NULL, target, GLOBAL_ROOT_UID, info, error); return error; } +const char *stack_msg = "change_profile unprivileged unconfined converted to stacking"; + /** * aa_change_profile - perform a one-way profile transition * @fqname: name of profile may include namespace (NOT NULL) @@ -1304,6 +1335,7 @@ int aa_change_profile(const char *fqname, int flags) const char *auditname = fqname; /* retain leading & if stack */ bool stack = flags & AA_CHANGE_STACK; struct aa_task_ctx *ctx = task_ctx(current); + const struct cred *subj_cred = get_current_cred(); int error = 0; char *op; u32 request; @@ -1340,6 +1372,28 @@ int aa_change_profile(const char *fqname, int flags) op = OP_CHANGE_PROFILE; } + /* This should move to a per profile test. Requires pushing build + * into callback + */ + if (!stack && unconfined(label) && + label == &labels_ns(label)->unconfined->label && + aa_unprivileged_unconfined_restricted && + /* TODO: refactor so this check is a fn */ + cap_capable(current_cred(), &init_user_ns, CAP_MAC_OVERRIDE, + CAP_OPT_NOAUDIT)) { + /* regardless of the request in this case apparmor + * stacks against unconfined so admin set policy can't be + * by-passed + */ + stack = true; + perms.audit = request; + (void) fn_for_each_in_ns(label, profile, + aa_audit_file(subj_cred, profile, &perms, op, + request, auditname, NULL, target, + GLOBAL_ROOT_UID, stack_msg, 0)); + perms.audit = 0; + } + if (*fqname == '&') { stack = true; /* don't have label_parse() do stacking */ @@ -1381,6 +1435,7 @@ int aa_change_profile(const char *fqname, int flags) */ error = fn_for_each_in_ns(label, profile, change_profile_perms_wrapper(op, auditname, + subj_cred, profile, target, stack, request, &perms)); if (error) @@ -1391,7 +1446,7 @@ int aa_change_profile(const char *fqname, int flags) check: /* check if tracing task is allowed to trace target domain */ - error = may_change_ptraced_domain(target, &info); + error = may_change_ptraced_domain(subj_cred, target, &info); if (error && !fn_for_each_in_ns(label, profile, COMPLAIN_MODE(profile))) goto audit; @@ -1446,12 +1501,13 @@ check: } /* full transition will be built in exec path */ - error = aa_set_current_onexec(target, stack); + aa_set_current_onexec(target, stack); } audit: error = fn_for_each_in_ns(label, profile, - aa_audit_file(profile, &perms, op, request, auditname, + aa_audit_file(subj_cred, + profile, &perms, op, request, auditname, NULL, new ? new : target, GLOBAL_ROOT_UID, info, error)); @@ -1459,6 +1515,7 @@ out: aa_put_label(new); aa_put_label(target); aa_put_label(label); + put_cred(subj_cred); return error; } diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 698b124e649f..c03eb7c19f16 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -44,38 +44,40 @@ static u32 map_mask_to_chr_mask(u32 mask) static void file_audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; - kuid_t fsuid = current_fsuid(); + struct apparmor_audit_data *ad = aad(sa); + kuid_t fsuid = ad->subj_cred ? ad->subj_cred->fsuid : current_fsuid(); char str[10]; - if (aad(sa)->request & AA_AUDIT_FILE_MASK) { + if (ad->request & AA_AUDIT_FILE_MASK) { aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs, - map_mask_to_chr_mask(aad(sa)->request)); + map_mask_to_chr_mask(ad->request)); audit_log_format(ab, " requested_mask=\"%s\"", str); } - if (aad(sa)->denied & AA_AUDIT_FILE_MASK) { + if (ad->denied & AA_AUDIT_FILE_MASK) { aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs, - map_mask_to_chr_mask(aad(sa)->denied)); + map_mask_to_chr_mask(ad->denied)); audit_log_format(ab, " denied_mask=\"%s\"", str); } - if (aad(sa)->request & AA_AUDIT_FILE_MASK) { + if (ad->request & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " fsuid=%d", from_kuid(&init_user_ns, fsuid)); audit_log_format(ab, " ouid=%d", - from_kuid(&init_user_ns, aad(sa)->fs.ouid)); + from_kuid(&init_user_ns, ad->fs.ouid)); } - if (aad(sa)->peer) { + if (ad->peer) { audit_log_format(ab, " target="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAG_VIEW_SUBNS, GFP_KERNEL); - } else if (aad(sa)->fs.target) { + } else if (ad->fs.target) { audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, aad(sa)->fs.target); + audit_log_untrustedstring(ab, ad->fs.target); } } /** * aa_audit_file - handle the auditing of file operations + * @subj_cred: cred of the subject * @profile: the profile being enforced (NOT NULL) * @perms: the permissions computed for the request (NOT NULL) * @op: operation being mediated @@ -89,59 +91,74 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) * * Returns: %0 or error on failure */ -int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, +int aa_audit_file(const struct cred *subj_cred, + struct aa_profile *profile, struct aa_perms *perms, const char *op, u32 request, const char *name, const char *target, struct aa_label *tlabel, kuid_t ouid, const char *info, int error) { int type = AUDIT_APPARMOR_AUTO; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); - sa.u.tsk = NULL; - aad(&sa)->request = request; - aad(&sa)->name = name; - aad(&sa)->fs.target = target; - aad(&sa)->peer = tlabel; - aad(&sa)->fs.ouid = ouid; - aad(&sa)->info = info; - aad(&sa)->error = error; - sa.u.tsk = NULL; + ad.subj_cred = subj_cred; + ad.request = request; + ad.name = name; + ad.fs.target = target; + ad.peer = tlabel; + ad.fs.ouid = ouid; + ad.info = info; + ad.error = error; + ad.common.u.tsk = NULL; - if (likely(!aad(&sa)->error)) { + if (likely(!ad.error)) { u32 mask = perms->audit; if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) mask = 0xffff; /* mask off perms that are not being force audited */ - aad(&sa)->request &= mask; + ad.request &= mask; - if (likely(!aad(&sa)->request)) + if (likely(!ad.request)) return 0; type = AUDIT_APPARMOR_AUDIT; } else { /* only report permissions that were denied */ - aad(&sa)->request = aad(&sa)->request & ~perms->allow; - AA_BUG(!aad(&sa)->request); + ad.request = ad.request & ~perms->allow; + AA_BUG(!ad.request); - if (aad(&sa)->request & perms->kill) + if (ad.request & perms->kill) type = AUDIT_APPARMOR_KILL; /* quiet known rejects, assumes quiet and kill do not overlap */ - if ((aad(&sa)->request & perms->quiet) && + if ((ad.request & perms->quiet) && AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_ALL) - aad(&sa)->request &= ~perms->quiet; + ad.request &= ~perms->quiet; - if (!aad(&sa)->request) - return aad(&sa)->error; + if (!ad.request) + return ad.error; } - aad(&sa)->denied = aad(&sa)->request & ~perms->allow; - return aa_audit(type, profile, &sa, file_audit_cb); + ad.denied = ad.request & ~perms->allow; + return aa_audit(type, profile, &ad, file_audit_cb); } -static int path_name(const char *op, struct aa_label *label, +/** + * is_deleted - test if a file has been completely unlinked + * @dentry: dentry of file to test for deletion (NOT NULL) + * + * Returns: true if deleted else false + */ +static inline bool is_deleted(struct dentry *dentry) +{ + if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) + return true; + return false; +} + +static int path_name(const char *op, const struct cred *subj_cred, + struct aa_label *label, const struct path *path, int flags, char *buffer, const char **name, struct path_cond *cond, u32 request) { @@ -153,7 +170,8 @@ static int path_name(const char *op, struct aa_label *label, labels_profile(label)->disconnected); if (error) { fn_for_each_confined(label, profile, - aa_audit_file(profile, &nullperms, op, request, *name, + aa_audit_file(subj_cred, + profile, &nullperms, op, request, *name, NULL, NULL, cond->uid, info, error)); return error; } @@ -164,7 +182,7 @@ static int path_name(const char *op, struct aa_label *label, struct aa_perms default_perms = {}; /** * aa_lookup_fperms - convert dfa compressed perms to internal perms - * @dfa: dfa to lookup perms for (NOT NULL) + * @file_rules: the aa_policydb to lookup perms for (NOT NULL) * @state: state in dfa * @cond: conditions to consider (NOT NULL) * @@ -188,8 +206,8 @@ struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules, /** * aa_str_perms - find permission that match @name - * @dfa: to match against (MAYBE NULL) - * @state: state to start matching in + * @file_rules: the aa_policydb to match against (NOT NULL) + * @start: state to start matching in * @name: string to match against dfa (NOT NULL) * @cond: conditions to consider for permission set computation (NOT NULL) * @perms: Returns - the permissions found when matching @name @@ -207,9 +225,9 @@ aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start, return state; } -static int __aa_path_perm(const char *op, struct aa_profile *profile, - const char *name, u32 request, - struct path_cond *cond, int flags, +static int __aa_path_perm(const char *op, const struct cred *subj_cred, + struct aa_profile *profile, const char *name, + u32 request, struct path_cond *cond, int flags, struct aa_perms *perms) { struct aa_ruleset *rules = list_first_entry(&profile->rules, @@ -218,16 +236,18 @@ static int __aa_path_perm(const char *op, struct aa_profile *profile, if (profile_unconfined(profile)) return 0; - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], name, cond, perms); if (request & ~perms->allow) e = -EACCES; - return aa_audit_file(profile, perms, op, request, name, NULL, NULL, + return aa_audit_file(subj_cred, + profile, perms, op, request, name, NULL, NULL, cond->uid, NULL, e); } -static int profile_path_perm(const char *op, struct aa_profile *profile, +static int profile_path_perm(const char *op, const struct cred *subj_cred, + struct aa_profile *profile, const struct path *path, char *buffer, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms) @@ -238,18 +258,19 @@ static int profile_path_perm(const char *op, struct aa_profile *profile, if (profile_unconfined(profile)) return 0; - error = path_name(op, &profile->label, path, + error = path_name(op, subj_cred, &profile->label, path, flags | profile->path_flags, buffer, &name, cond, request); if (error) return error; - return __aa_path_perm(op, profile, name, request, cond, flags, - perms); + return __aa_path_perm(op, subj_cred, profile, name, request, cond, + flags, perms); } /** * aa_path_perm - do permissions check & audit for @path * @op: operation being checked + * @subj_cred: subject cred * @label: profile being enforced (NOT NULL) * @path: path to check permissions of (NOT NULL) * @flags: any additional path flags beyond what the profile specifies @@ -258,7 +279,8 @@ static int profile_path_perm(const char *op, struct aa_profile *profile, * * Returns: %0 else error if access denied or other error */ -int aa_path_perm(const char *op, struct aa_label *label, +int aa_path_perm(const char *op, const struct cred *subj_cred, + struct aa_label *label, const struct path *path, int flags, u32 request, struct path_cond *cond) { @@ -273,8 +295,8 @@ int aa_path_perm(const char *op, struct aa_label *label, if (!buffer) return -ENOMEM; error = fn_for_each_confined(label, profile, - profile_path_perm(op, profile, path, buffer, request, - cond, flags, &perms)); + profile_path_perm(op, subj_cred, profile, path, buffer, + request, cond, flags, &perms)); aa_put_buffer(buffer); @@ -301,7 +323,8 @@ static inline bool xindex_is_subset(u32 link, u32 target) return true; } -static int profile_path_link(struct aa_profile *profile, +static int profile_path_link(const struct cred *subj_cred, + struct aa_profile *profile, const struct path *link, char *buffer, const struct path *target, char *buffer2, struct path_cond *cond) @@ -315,29 +338,31 @@ static int profile_path_link(struct aa_profile *profile, aa_state_t state; int error; - error = path_name(OP_LINK, &profile->label, link, profile->path_flags, + error = path_name(OP_LINK, subj_cred, &profile->label, link, + profile->path_flags, buffer, &lname, cond, AA_MAY_LINK); if (error) goto audit; /* buffer2 freed below, tname is pointer in buffer2 */ - error = path_name(OP_LINK, &profile->label, target, profile->path_flags, + error = path_name(OP_LINK, subj_cred, &profile->label, target, + profile->path_flags, buffer2, &tname, cond, AA_MAY_LINK); if (error) goto audit; error = -EACCES; /* aa_str_perms - handles the case of the dfa being NULL */ - state = aa_str_perms(&(rules->file), - rules->file.start[AA_CLASS_FILE], lname, + state = aa_str_perms(rules->file, + rules->file->start[AA_CLASS_FILE], lname, cond, &lperms); if (!(lperms.allow & AA_MAY_LINK)) goto audit; /* test to see if target can be paired with link */ - state = aa_dfa_null_transition(rules->file.dfa, state); - aa_str_perms(&(rules->file), state, tname, cond, &perms); + state = aa_dfa_null_transition(rules->file->dfa, state); + aa_str_perms(rules->file, state, tname, cond, &perms); /* force audit/quiet masks for link are stored in the second entry * in the link pair. @@ -359,7 +384,7 @@ static int profile_path_link(struct aa_profile *profile, /* Do link perm subset test requiring allowed permission on link are * a subset of the allowed permissions on target. */ - aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE], tname, cond, &perms); /* AA_MAY_LINK is not considered in the subset test */ @@ -381,12 +406,14 @@ done_tests: error = 0; audit: - return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname, + return aa_audit_file(subj_cred, + profile, &lperms, OP_LINK, request, lname, tname, NULL, cond->uid, info, error); } /** * aa_path_link - Handle hard link permission check + * @subj_cred: subject cred * @label: the label being enforced (NOT NULL) * @old_dentry: the target dentry (NOT NULL) * @new_dir: directory the new link will be created in (NOT NULL) @@ -403,7 +430,8 @@ audit: * * Returns: %0 if allowed else error */ -int aa_path_link(struct aa_label *label, struct dentry *old_dentry, +int aa_path_link(const struct cred *subj_cred, + struct aa_label *label, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry }; @@ -424,8 +452,8 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry, goto out; error = fn_for_each_confined(label, profile, - profile_path_link(profile, &link, buffer, &target, - buffer2, &cond)); + profile_path_link(subj_cred, profile, &link, buffer, + &target, buffer2, &cond)); out: aa_put_buffer(buffer); aa_put_buffer(buffer2); @@ -453,7 +481,8 @@ static void update_file_ctx(struct aa_file_ctx *fctx, struct aa_label *label, spin_unlock(&fctx->lock); } -static int __file_path_perm(const char *op, struct aa_label *label, +static int __file_path_perm(const char *op, const struct cred *subj_cred, + struct aa_label *label, struct aa_label *flabel, struct file *file, u32 request, u32 denied, bool in_atomic) { @@ -480,7 +509,8 @@ static int __file_path_perm(const char *op, struct aa_label *label, /* check every profile in task label not in current cache */ error = fn_for_each_not_in_set(flabel, label, profile, - profile_path_perm(op, profile, &file->f_path, buffer, + profile_path_perm(op, subj_cred, profile, + &file->f_path, buffer, request, &cond, flags, &perms)); if (denied && !error) { /* @@ -493,12 +523,14 @@ static int __file_path_perm(const char *op, struct aa_label *label, */ if (label == flabel) error = fn_for_each(label, profile, - profile_path_perm(op, profile, &file->f_path, + profile_path_perm(op, subj_cred, + profile, &file->f_path, buffer, request, &cond, flags, &perms)); else error = fn_for_each_not_in_set(label, flabel, profile, - profile_path_perm(op, profile, &file->f_path, + profile_path_perm(op, subj_cred, + profile, &file->f_path, buffer, request, &cond, flags, &perms)); } @@ -510,7 +542,8 @@ static int __file_path_perm(const char *op, struct aa_label *label, return error; } -static int __file_sock_perm(const char *op, struct aa_label *label, +static int __file_sock_perm(const char *op, const struct cred *subj_cred, + struct aa_label *label, struct aa_label *flabel, struct file *file, u32 request, u32 denied) { @@ -524,11 +557,12 @@ static int __file_sock_perm(const char *op, struct aa_label *label, return 0; /* TODO: improve to skip profiles cached in flabel */ - error = aa_sock_file_perm(label, op, request, sock); + error = aa_sock_file_perm(subj_cred, label, op, request, sock); if (denied) { /* TODO: improve to skip profiles checked above */ /* check every profile in file label to is cached */ - last_error(error, aa_sock_file_perm(flabel, op, request, sock)); + last_error(error, aa_sock_file_perm(subj_cred, flabel, op, + request, sock)); } if (!error) update_file_ctx(file_ctx(file), label, request); @@ -539,6 +573,7 @@ static int __file_sock_perm(const char *op, struct aa_label *label, /** * aa_file_perm - do permission revalidation check & audit for @file * @op: operation being checked + * @subj_cred: subject cred * @label: label being enforced (NOT NULL) * @file: file to revalidate access permissions on (NOT NULL) * @request: requested permissions @@ -546,7 +581,8 @@ static int __file_sock_perm(const char *op, struct aa_label *label, * * Returns: %0 if access allowed else error */ -int aa_file_perm(const char *op, struct aa_label *label, struct file *file, +int aa_file_perm(const char *op, const struct cred *subj_cred, + struct aa_label *label, struct file *file, u32 request, bool in_atomic) { struct aa_file_ctx *fctx; @@ -582,19 +618,19 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file, /* TODO: label cross check */ if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) - error = __file_path_perm(op, label, flabel, file, request, - denied, in_atomic); + error = __file_path_perm(op, subj_cred, label, flabel, file, + request, denied, in_atomic); else if (S_ISSOCK(file_inode(file)->i_mode)) - error = __file_sock_perm(op, label, flabel, file, request, - denied); + error = __file_sock_perm(op, subj_cred, label, flabel, file, + request, denied); aa_put_label(flabel); done: return error; } -static void revalidate_tty(struct aa_label *label) +static void revalidate_tty(const struct cred *subj_cred, struct aa_label *label) { struct tty_struct *tty; int drop_tty = 0; @@ -612,8 +648,8 @@ static void revalidate_tty(struct aa_label *label) struct tty_file_private, list); file = file_priv->file; - if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE, - IN_ATOMIC)) + if (aa_file_perm(OP_INHERIT, subj_cred, label, file, + MAY_READ | MAY_WRITE, IN_ATOMIC)) drop_tty = 1; } spin_unlock(&tty->files_lock); @@ -623,12 +659,17 @@ static void revalidate_tty(struct aa_label *label) no_tty(); } +struct cred_label { + const struct cred *cred; + struct aa_label *label; +}; + static int match_file(const void *p, struct file *file, unsigned int fd) { - struct aa_label *label = (struct aa_label *)p; + struct cred_label *cl = (struct cred_label *)p; - if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file), - IN_ATOMIC)) + if (aa_file_perm(OP_INHERIT, cl->cred, cl->label, file, + aa_map_file_to_perms(file), IN_ATOMIC)) return fd + 1; return 0; } @@ -638,13 +679,17 @@ static int match_file(const void *p, struct file *file, unsigned int fd) void aa_inherit_files(const struct cred *cred, struct files_struct *files) { struct aa_label *label = aa_get_newest_cred_label(cred); + struct cred_label cl = { + .cred = cred, + .label = label, + }; struct file *devnull = NULL; unsigned int n; - revalidate_tty(label); + revalidate_tty(cred, label); /* Revalidate access to inherited open files. */ - n = iterate_fd(files, 0, match_file, label); + n = iterate_fd(files, 0, match_file, &cl); if (!n) /* none found? */ goto out; @@ -654,7 +699,7 @@ void aa_inherit_files(const struct cred *cred, struct files_struct *files) /* replace all the matching ones with this */ do { replace_fd(n - 1, devnull, 0); - } while ((n = iterate_fd(files, n, match_file, label)) != 0); + } while ((n = iterate_fd(files, n, match_file, &cl)) != 0); if (devnull) fput(devnull); out: diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index 8a81557c9d59..f83934913b0f 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -30,9 +30,10 @@ #define AA_CLASS_NET 14 #define AA_CLASS_LABEL 16 #define AA_CLASS_POSIX_MQUEUE 17 -#define AA_CLASS_IO_URING 18 #define AA_CLASS_MODULE 19 #define AA_CLASS_DISPLAY_LSM 20 +#define AA_CLASS_NS 21 +#define AA_CLASS_IO_URING 22 #define AA_CLASS_X 31 #define AA_CLASS_DBUS 32 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index c328f07f11cd..acbb03b9bd25 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -103,13 +103,18 @@ enum audit_type { #define OP_PROF_LOAD "profile_load" #define OP_PROF_RM "profile_remove" +#define OP_USERNS_CREATE "userns_create" + +#define OP_URING_OVERRIDE "uring_override" +#define OP_URING_SQPOLL "uring_sqpoll" struct apparmor_audit_data { int error; int type; u16 class; const char *op; - struct aa_label *label; + const struct cred *subj_cred; + struct aa_label *subj_label; const char *name; const char *info; u32 request; @@ -151,34 +156,39 @@ struct apparmor_audit_data { const char *data; unsigned long flags; } mnt; + struct { + struct aa_label *target; + } uring; }; + + struct common_audit_data common; }; /* macros for dealing with apparmor_audit_data structure */ -#define aad(SA) ((SA)->apparmor_audit_data) +#define aad(SA) (container_of(SA, struct apparmor_audit_data, common)) +#define aad_of_va(VA) aad((struct common_audit_data *)(VA)) + #define DEFINE_AUDIT_DATA(NAME, T, C, X) \ /* TODO: cleanup audit init so we don't need _aad = {0,} */ \ - struct apparmor_audit_data NAME ## _aad = { \ + struct apparmor_audit_data NAME = { \ .class = (C), \ .op = (X), \ - }; \ - struct common_audit_data NAME = \ - { \ - .type = (T), \ - .u.tsk = NULL, \ - }; \ - NAME.apparmor_audit_data = &(NAME ## _aad) + .common.type = (T), \ + .common.u.tsk = NULL, \ + .common.apparmor_audit_data = &NAME, \ + }; -void aa_audit_msg(int type, struct common_audit_data *sa, +void aa_audit_msg(int type, struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)); -int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, +int aa_audit(int type, struct aa_profile *profile, + struct apparmor_audit_data *ad, void (*cb) (struct audit_buffer *, void *)); -#define aa_audit_error(ERROR, SA, CB) \ +#define aa_audit_error(ERROR, AD, CB) \ ({ \ - aad((SA))->error = (ERROR); \ - aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB)); \ - aad((SA))->error; \ + (AD)->error = (ERROR); \ + aa_audit_msg(AUDIT_APPARMOR_ERROR, (AD), (CB)); \ + (AD)->error; \ }) diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h index d420e2d10b31..d6dcc604ec0c 100644 --- a/security/apparmor/include/capability.h +++ b/security/apparmor/include/capability.h @@ -36,7 +36,8 @@ struct aa_caps { extern struct aa_sfs_entry aa_sfs_entry_caps[]; -int aa_capable(struct aa_label *label, int cap, unsigned int opts); +int aa_capable(const struct cred *subj_cred, struct aa_label *label, + int cap, unsigned int opts); static inline void aa_free_cap_rules(struct aa_caps *caps) { diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index 5be620af33ba..6e8f2aa66cd6 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h @@ -45,43 +45,6 @@ struct aa_file_ctx { u32 allow; }; -/** - * aa_alloc_file_ctx - allocate file_ctx - * @label: initial label of task creating the file - * @gfp: gfp flags for allocation - * - * Returns: file_ctx or NULL on failure - */ -static inline struct aa_file_ctx *aa_alloc_file_ctx(struct aa_label *label, - gfp_t gfp) -{ - struct aa_file_ctx *ctx; - - ctx = kzalloc(sizeof(struct aa_file_ctx), gfp); - if (ctx) { - spin_lock_init(&ctx->lock); - rcu_assign_pointer(ctx->label, aa_get_label(label)); - } - return ctx; -} - -/** - * aa_free_file_ctx - free a file_ctx - * @ctx: file_ctx to free (MAYBE_NULL) - */ -static inline void aa_free_file_ctx(struct aa_file_ctx *ctx) -{ - if (ctx) { - aa_put_label(rcu_access_pointer(ctx->label)); - kfree_sensitive(ctx); - } -} - -static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx) -{ - return aa_get_label_rcu(&ctx->label); -} - /* * The xindex is broken into 3 parts * - index - an index into either the exec name table or the variable table @@ -108,7 +71,8 @@ struct path_cond { #define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) -int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, +int aa_audit_file(const struct cred *cred, + struct aa_profile *profile, struct aa_perms *perms, const char *op, u32 request, const char *name, const char *target, struct aa_label *tlabel, kuid_t ouid, const char *info, int error); @@ -119,14 +83,16 @@ aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start, const char *name, struct path_cond *cond, struct aa_perms *perms); -int aa_path_perm(const char *op, struct aa_label *label, - const struct path *path, int flags, u32 request, - struct path_cond *cond); +int aa_path_perm(const char *op, const struct cred *subj_cred, + struct aa_label *label, const struct path *path, + int flags, u32 request, struct path_cond *cond); -int aa_path_link(struct aa_label *label, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry); +int aa_path_link(const struct cred *subj_cred, struct aa_label *label, + struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry); -int aa_file_perm(const char *op, struct aa_label *label, struct file *file, +int aa_file_perm(const char *op, const struct cred *subj_cred, + struct aa_label *label, struct file *file, u32 request, bool in_atomic); void aa_inherit_files(const struct cred *cred, struct files_struct *files); diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h index a1ac6ffb95e9..74d17052f76b 100644 --- a/security/apparmor/include/ipc.h +++ b/security/apparmor/include/ipc.h @@ -13,6 +13,8 @@ #include -int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); +int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender, + const struct cred *target_cred, struct aa_label *target, + int sig); #endif /* __AA_IPC_H */ diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index 73c8a32c6861..d7a894b1031f 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h @@ -16,6 +16,8 @@ #include "match.h" +extern struct aa_dfa *stacksplitdfa; + /* * DEBUG remains global (no per profile flag) since it is mostly used in sysctl * which is not related to profile accesses. diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h index 58fbf67139b9..4bb0405c9190 100644 --- a/security/apparmor/include/match.h +++ b/security/apparmor/include/match.h @@ -102,9 +102,6 @@ struct aa_dfa { struct table_header *tables[YYTD_ID_TSIZE]; }; -extern struct aa_dfa *nulldfa; -extern struct aa_dfa *stacksplitdfa; - #define byte_to_byte(X) (X) #define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \ @@ -122,9 +119,6 @@ static inline size_t table_size(size_t len, size_t el_size) return ALIGN(sizeof(struct table_header) + len * el_size, 8); } -int aa_setup_dfa_engine(void); -void aa_teardown_dfa_engine(void); - #define aa_state_t unsigned int struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h index a710683b2496..46834f828179 100644 --- a/security/apparmor/include/mount.h +++ b/security/apparmor/include/mount.h @@ -25,26 +25,36 @@ #define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN) -int aa_remount(struct aa_label *label, const struct path *path, +int aa_remount(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, unsigned long flags, void *data); -int aa_bind_mount(struct aa_label *label, const struct path *path, +int aa_bind_mount(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, const char *old_name, unsigned long flags); -int aa_mount_change_type(struct aa_label *label, const struct path *path, +int aa_mount_change_type(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, unsigned long flags); -int aa_move_mount(struct aa_label *label, const struct path *path, - const char *old_name); +int aa_move_mount_old(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, + const char *old_name); +int aa_move_mount(const struct cred *subj_cred, + struct aa_label *label, const struct path *from_path, + const struct path *to_path); -int aa_new_mount(struct aa_label *label, const char *dev_name, +int aa_new_mount(const struct cred *subj_cred, + struct aa_label *label, const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data); -int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags); +int aa_umount(const struct cred *subj_cred, + struct aa_label *label, struct vfsmount *mnt, int flags); -int aa_pivotroot(struct aa_label *label, const struct path *old_path, +int aa_pivotroot(const struct cred *subj_cred, + struct aa_label *label, const struct path *old_path, const struct path *new_path); #endif /* __AA_MOUNT_H */ diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index 6fa440b5daed..67bf888c3bd6 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h @@ -52,7 +52,11 @@ struct aa_sk_ctx { }; #define SK_CTX(X) ((X)->sk_security) -#define SOCK_ctx(X) SOCK_INODE(X)->i_security +static inline struct aa_sk_ctx *aa_sock(const struct sock *sk) +{ + return sk->sk_security; +} + #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \ struct lsm_network_audit NAME ## _net = { .sk = (SK), \ .family = (F)}; \ @@ -61,9 +65,9 @@ struct aa_sk_ctx { LSM_AUDIT_DATA_NONE, \ AA_CLASS_NET, \ OP); \ - NAME.u.net = &(NAME ## _net); \ - aad(&NAME)->net.type = (T); \ - aad(&NAME)->net.protocol = (P) + NAME.common.u.net = &(NAME ## _net); \ + NAME.net.type = (T); \ + NAME.net.protocol = (P) #define DEFINE_AUDIT_SK(NAME, OP, SK) \ DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \ @@ -90,21 +94,24 @@ struct aa_secmark { extern struct aa_sfs_entry aa_sfs_entry_network[]; void audit_net_cb(struct audit_buffer *ab, void *va); -int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, +int aa_profile_af_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, u32 request, u16 family, int type); -int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, +int aa_af_perm(const struct cred *subj_cred, struct aa_label *label, + const char *op, u32 request, u16 family, int type, int protocol); static inline int aa_profile_af_sk_perm(struct aa_profile *profile, - struct common_audit_data *sa, + struct apparmor_audit_data *ad, u32 request, struct sock *sk) { - return aa_profile_af_perm(profile, sa, request, sk->sk_family, + return aa_profile_af_perm(profile, ad, request, sk->sk_family, sk->sk_type); } int aa_sk_perm(const char *op, u32 request, struct sock *sk); -int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, +int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, + const char *op, u32 request, struct socket *sock); int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h index 797a7a00644d..0f7e913c3fc2 100644 --- a/security/apparmor/include/perms.h +++ b/security/apparmor/include/perms.h @@ -48,6 +48,9 @@ #define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ +#define AA_MAY_CREATE_SQPOLL AA_MAY_CREATE +#define AA_MAY_OVERRIDE_CRED AA_MAY_APPEND +#define AA_URING_PERM_MASK (AA_MAY_OVERRIDE_CRED | AA_MAY_CREATE_SQPOLL) #define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \ AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \ @@ -212,8 +215,8 @@ void aa_profile_match_label(struct aa_profile *profile, int type, u32 request, struct aa_perms *perms); int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, u32 request, int type, u32 *deny, - struct common_audit_data *sa); + struct apparmor_audit_data *ad); int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, - u32 request, struct common_audit_data *sa, + u32 request, struct apparmor_audit_data *ad, void (*cb)(struct audit_buffer *, void *)); #endif /* __AA_PERM_H */ diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 545f791cabda..75088cc310b6 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -34,6 +34,7 @@ struct aa_ns; extern int unprivileged_userns_apparmor_policy; +extern int aa_unprivileged_unconfined_restricted; extern const char *const aa_profile_mode_names[]; #define APPARMOR_MODE_NAMES_MAX_INDEX 4 @@ -74,12 +75,14 @@ enum profile_mode { /* struct aa_policydb - match engine for a policy + * count: refcount for the pdb * dfa: dfa pattern match * perms: table of permissions * strs: table of strings, index by x * start: set of start states for the different classes of data */ struct aa_policydb { + struct kref count; struct aa_dfa *dfa; struct { struct aa_perms *perms; @@ -89,13 +92,36 @@ struct aa_policydb { aa_state_t start[AA_CLASS_LAST + 1]; }; -static inline void aa_destroy_policydb(struct aa_policydb *policy) -{ - aa_put_dfa(policy->dfa); - if (policy->perms) - kvfree(policy->perms); - aa_free_str_table(&policy->trans); +extern struct aa_policydb *nullpdb; +struct aa_policydb *aa_alloc_pdb(gfp_t gfp); +void aa_pdb_free_kref(struct kref *kref); + +/** + * aa_get_pdb - increment refcount on @pdb + * @pdb: policydb (MAYBE NULL) + * + * Returns: pointer to @pdb if @pdb is NULL will return NULL + * Requires: @pdb must be held with valid refcount when called + */ +static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb) +{ + if (pdb) + kref_get(&(pdb->count)); + + return pdb; +} + +/** + * aa_put_pdb - put a pdb refcount + * @pdb: pdb to put refcount (MAYBE NULL) + * + * Requires: if @pdb != NULL that a valid refcount be held + */ +static inline void aa_put_pdb(struct aa_policydb *pdb) +{ + if (pdb) + kref_put(&pdb->count, aa_pdb_free_kref); } static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, @@ -139,8 +165,8 @@ struct aa_ruleset { int size; /* TODO: merge policy and file */ - struct aa_policydb policy; - struct aa_policydb file; + struct aa_policydb *policy; + struct aa_policydb *file; struct aa_caps caps; struct aa_rlimit rlimits; @@ -159,7 +185,7 @@ struct aa_ruleset { */ struct aa_attachment { const char *xmatch_str; - struct aa_policydb xmatch; + struct aa_policydb *xmatch; unsigned int xmatch_len; int xattr_count; char **xattrs; @@ -227,10 +253,6 @@ extern enum profile_mode aa_g_profile_mode; #define profiles_ns(P) ((P)->ns) #define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname) -void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); - - -void aa_free_proxy_kref(struct kref *kref); struct aa_ruleset *aa_alloc_ruleset(gfp_t gfp); struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, gfp_t gfp); @@ -239,14 +261,12 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, struct aa_profile *aa_new_learning_profile(struct aa_profile *parent, bool hat, const char *base, gfp_t gfp); void aa_free_profile(struct aa_profile *profile); -void aa_free_profile_kref(struct kref *kref); struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, size_t n); struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, const char *fqname, size_t n); -struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label, u32 mask, struct aa_loaddata *udata); @@ -254,9 +274,6 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label, char *name, size_t size); void __aa_profile_list_release(struct list_head *head); -#define PROF_ADD 1 -#define PROF_REPLACE 0 - #define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) /** @@ -276,10 +293,10 @@ static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules, unsigned char class) { if (class <= AA_CLASS_LAST) - return rules->policy.start[class]; + return rules->policy->start[class]; else - return aa_dfa_match_len(rules->policy.dfa, - rules->policy.start[0], &class, 1); + return aa_dfa_match_len(rules->policy->dfa, + rules->policy->start[0], &class, 1); } static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) @@ -289,7 +306,7 @@ static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) if (!state) return DFA_NOMATCH; - return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); + return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); } static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, @@ -370,9 +387,12 @@ static inline int AUDIT_MODE(struct aa_profile *profile) return profile->audit; } -bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns); -bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns); -int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, +bool aa_policy_view_capable(const struct cred *subj_cred, + struct aa_label *label, struct aa_ns *ns); +bool aa_policy_admin_capable(const struct cred *subj_cred, + struct aa_label *label, struct aa_ns *ns); +int aa_may_manage_policy(const struct cred *subj_cred, + struct aa_label *label, struct aa_ns *ns, u32 mask); bool aa_current_policy_view_capable(struct aa_ns *ns); bool aa_current_policy_admin_capable(struct aa_ns *ns); diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h index 33d665516fc1..d646070fd966 100644 --- a/security/apparmor/include/policy_ns.h +++ b/security/apparmor/include/policy_ns.h @@ -86,10 +86,7 @@ const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns); void aa_free_ns(struct aa_ns *ns); int aa_alloc_root_ns(void); void aa_free_root_ns(void); -void aa_free_ns_kref(struct kref *kref); -struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name); -struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n); struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n); struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n); struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, @@ -151,15 +148,4 @@ static inline struct aa_ns *__aa_find_ns(struct list_head *head, return __aa_findn_ns(head, name, strlen(name)); } -static inline struct aa_ns *__aa_lookup_ns(struct aa_ns *base, - const char *hname) -{ - return __aa_lookupn_ns(base, hname, strlen(hname)); -} - -static inline struct aa_ns *aa_lookup_ns(struct aa_ns *view, const char *name) -{ - return aa_lookupn_ns(view, name, strlen(name)); -} - #endif /* AA_NAMESPACE_H */ diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h index 961d85d328ea..ad2c0da8e64f 100644 --- a/security/apparmor/include/resource.h +++ b/security/apparmor/include/resource.h @@ -33,7 +33,8 @@ struct aa_rlimit { extern struct aa_sfs_entry aa_sfs_entry_rlimit[]; int aa_map_resource(int resource); -int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, +int aa_task_setrlimit(const struct cred *subj_cred, struct aa_label *label, + struct task_struct *task, unsigned int resource, struct rlimit *new_rlim); void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new); diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h index 13437d62c70f..b1aaaf60fa8b 100644 --- a/security/apparmor/include/task.h +++ b/security/apparmor/include/task.h @@ -30,7 +30,7 @@ struct aa_task_ctx { }; int aa_replace_current_label(struct aa_label *label); -int aa_set_current_onexec(struct aa_label *label, bool stack); +void aa_set_current_onexec(struct aa_label *label, bool stack); int aa_set_current_hat(struct aa_label *label, u64 token); int aa_restore_previous_label(u64 cookie); struct aa_label *aa_get_task_label(struct task_struct *task); @@ -91,8 +91,15 @@ static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \ "xcpu xfsz vtalrm prof winch io pwr sys emt lost" -int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, +int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer, + const struct cred *tracee_cred, struct aa_label *tracee, u32 request); + +#define AA_USERNS_CREATE 8 + +int aa_profile_ns_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, u32 request); + #endif /* __AA_TASK_H */ diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index 5acde746775f..0cdf4340b02d 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -52,31 +52,33 @@ static const char *audit_signal_mask(u32 mask) static void audit_signal_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { + if (ad->request & AA_SIGNAL_PERM_MASK) { audit_log_format(ab, " requested_mask=\"%s\"", - audit_signal_mask(aad(sa)->request)); - if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { + audit_signal_mask(ad->request)); + if (ad->denied & AA_SIGNAL_PERM_MASK) { audit_log_format(ab, " denied_mask=\"%s\"", - audit_signal_mask(aad(sa)->denied)); + audit_signal_mask(ad->denied)); } } - if (aad(sa)->signal == SIGUNKNOWN) + if (ad->signal == SIGUNKNOWN) audit_log_format(ab, "signal=unknown(%d)", - aad(sa)->unmappedsig); - else if (aad(sa)->signal < MAXMAPPED_SIGNAME) - audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); + ad->unmappedsig); + else if (ad->signal < MAXMAPPED_SIGNAME) + audit_log_format(ab, " signal=%s", sig_names[ad->signal]); else audit_log_format(ab, " signal=rtmin+%d", - aad(sa)->signal - SIGRT_BASE); + ad->signal - SIGRT_BASE); audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } -static int profile_signal_perm(struct aa_profile *profile, +static int profile_signal_perm(const struct cred *cred, + struct aa_profile *profile, struct aa_label *peer, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); @@ -87,24 +89,29 @@ static int profile_signal_perm(struct aa_profile *profile, !ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_SIGNAL)) return 0; - aad(sa)->peer = peer; + ad->subj_cred = cred; + ad->peer = peer; /* TODO: secondary cache check */ - state = aa_dfa_next(rules->policy.dfa, - rules->policy.start[AA_CLASS_SIGNAL], - aad(sa)->signal); + state = aa_dfa_next(rules->policy->dfa, + rules->policy->start[AA_CLASS_SIGNAL], + ad->signal); aa_label_match(profile, rules, peer, state, false, request, &perms); aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); + return aa_check_perms(profile, &perms, request, ad, audit_signal_cb); } -int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) +int aa_may_signal(const struct cred *subj_cred, struct aa_label *sender, + const struct cred *target_cred, struct aa_label *target, + int sig) { struct aa_profile *profile; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_SIGNAL, OP_SIGNAL); - aad(&sa)->signal = map_signal_num(sig); - aad(&sa)->unmappedsig = sig; + ad.signal = map_signal_num(sig); + ad.unmappedsig = sig; return xcheck_labels(sender, target, profile, - profile_signal_perm(profile, target, MAY_WRITE, &sa), - profile_signal_perm(profile, sender, MAY_READ, &sa)); + profile_signal_perm(subj_cred, profile, target, + MAY_WRITE, &ad), + profile_signal_perm(target_cred, profile, sender, + MAY_READ, &ad)); } diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 8a2af96f4da5..c71e4615dd46 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -154,13 +154,14 @@ static int profile_cmp(struct aa_profile *a, struct aa_profile *b) /** * vec_cmp - label comparison for set ordering - * @a: label to compare (NOT NULL) - * @vec: vector of profiles to compare (NOT NULL) - * @n: length of @vec + * @a: aa_profile to compare (NOT NULL) + * @an: length of @a + * @b: aa_profile to compare (NOT NULL) + * @bn: length of @b * - * Returns: <0 if a < vec - * ==0 if a == vec - * >0 if a > vec + * Returns: <0 if @a < @b + * ==0 if @a == @b + * >0 if @a > @b */ static int vec_cmp(struct aa_profile **a, int an, struct aa_profile **b, int bn) { @@ -256,6 +257,7 @@ static inline int unique(struct aa_profile **vec, int n) * aa_vec_unique - canonical sort and unique a list of profiles * @n: number of refcounted profiles in the list (@n > 0) * @vec: list of profiles to sort and merge + * @flags: null terminator flags of @vec * * Returns: the number of duplicates eliminated == references put * @@ -584,7 +586,7 @@ bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub) /** * __label_remove - remove @label from the label set - * @l: label to remove + * @label: label to remove * @new: label to redirect to * * Requires: labels_set(@label)->lock write_lock @@ -917,8 +919,8 @@ struct aa_label *aa_label_find(struct aa_label *label) /** * aa_label_insert - insert label @label into @ls or return existing label - * @ls - labelset to insert @label into - * @label - label to insert + * @ls: labelset to insert @label into + * @label: label to insert * * Requires: caller to hold a valid ref on @label * @@ -1204,7 +1206,6 @@ struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b) /** * aa_label_merge - attempt to insert new merged label of @a and @b - * @ls: set of labels to insert label into (NOT NULL) * @a: label to merge with @b (NOT NULL) * @b: label to merge with @a (NOT NULL) * @gfp: memory allocation type @@ -1269,21 +1270,22 @@ static inline aa_state_t match_component(struct aa_profile *profile, const char *ns_name; if (profile->ns == tp->ns) - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); /* try matching with namespace name and then profile */ ns_name = aa_ns_name(profile->ns, tp->ns, true); - state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); - state = aa_dfa_match(rules->policy.dfa, state, ns_name); - state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); - return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); + state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); + state = aa_dfa_match(rules->policy->dfa, state, ns_name); + state = aa_dfa_match_len(rules->policy->dfa, state, ":", 1); + return aa_dfa_match(rules->policy->dfa, state, tp->base.hname); } /** * label_compound_match - find perms for full compound label * @profile: profile to find perms for + * @rules: ruleset to search * @label: label to check access permissions for - * @start: state to start match in + * @state: state to start match in * @subns: whether to do permission checks on components in a subns * @request: permissions to request * @perms: perms struct to set @@ -1321,12 +1323,12 @@ next: label_for_each_cont(i, label, tp) { if (!aa_ns_visible(profile->ns, tp->ns, subns)) continue; - state = aa_dfa_match(rules->policy.dfa, state, "//&"); + state = aa_dfa_match(rules->policy->dfa, state, "//&"); state = match_component(profile, rules, tp, state); if (!state) goto fail; } - *perms = *aa_lookup_perms(&rules->policy, state); + *perms = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, perms); if ((perms->allow & request) != request) return -EACCES; @@ -1379,7 +1381,7 @@ static int label_components_match(struct aa_profile *profile, return 0; next: - tmp = *aa_lookup_perms(&rules->policy, state); + tmp = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); label_for_each_cont(i, label, tp) { @@ -1388,7 +1390,7 @@ next: state = match_component(profile, rules, tp, start); if (!state) goto fail; - tmp = *aa_lookup_perms(&rules->policy, state); + tmp = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &tmp); aa_perms_accum(perms, &tmp); } @@ -2037,7 +2039,7 @@ out: /** * __label_update - insert updated version of @label into labelset - * @label - the label to update/replace + * @label: the label to update/replace * * Returns: new label that is up to date * else NULL on failure diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index a630c951bb3b..4c198d273f09 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -27,7 +27,7 @@ struct aa_perms allperms = { .allow = ALL_PERMS_MASK, /** * aa_free_str_table - free entries str table - * @str: the string table to free (MAYBE NULL) + * @t: the string table to free (MAYBE NULL) */ void aa_free_str_table(struct aa_str_table *t) { @@ -85,6 +85,7 @@ char *aa_split_fqname(char *fqname, char **ns_name) /** * skipn_spaces - Removes leading whitespace from @str. * @str: The string to be stripped. + * @n: length of str to parse, will stop at \0 if encountered before n * * Returns a pointer to the first non-whitespace character in @str. * if all whitespace will return NULL @@ -143,10 +144,10 @@ const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, void aa_info_message(const char *str) { if (audit_enabled) { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); - aad(&sa)->info = str; - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); + ad.info = str; + aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, NULL); } printk(KERN_INFO "AppArmor: %s\n", str); } @@ -281,21 +282,22 @@ void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->request) { + if (ad->request) { audit_log_format(ab, " requested_mask="); - aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, + aa_audit_perm_mask(ab, ad->request, aa_file_perm_chrs, PERMS_CHRS_MASK, aa_file_perm_names, PERMS_NAMES_MASK); } - if (aad(sa)->denied) { + if (ad->denied) { audit_log_format(ab, "denied_mask="); - aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, + aa_audit_perm_mask(ab, ad->denied, aa_file_perm_chrs, PERMS_CHRS_MASK, aa_file_perm_names, PERMS_NAMES_MASK); } audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } @@ -339,8 +341,8 @@ void aa_profile_match_label(struct aa_profile *profile, /* TODO: doesn't yet handle extended types */ aa_state_t state; - state = aa_dfa_next(rules->policy.dfa, - rules->policy.start[AA_CLASS_LABEL], + state = aa_dfa_next(rules->policy->dfa, + rules->policy->start[AA_CLASS_LABEL], type); aa_label_match(profile, rules, label, state, false, request, perms); } @@ -349,21 +351,20 @@ void aa_profile_match_label(struct aa_profile *profile, /* currently unused */ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, u32 request, int type, u32 *deny, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); struct aa_perms perms; - aad(sa)->label = &profile->label; - aad(sa)->peer = &target->label; - aad(sa)->request = request; + ad->peer = &target->label; + ad->request = request; aa_profile_match_label(profile, rules, &target->label, type, request, &perms); aa_apply_modes_to_perms(profile, &perms); *deny |= request & perms.deny; - return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); + return aa_check_perms(profile, &perms, request, ad, aa_audit_perms_cb); } /** @@ -371,8 +372,7 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, * @profile: profile being checked * @perms: perms computed for the request * @request: requested perms - * @deny: Returns: explicit deny set - * @sa: initialized audit structure (MAY BE NULL if not auditing) + * @ad: initialized audit structure (MAY BE NULL if not auditing) * @cb: callback fn for type specific fields (MAY BE NULL) * * Returns: 0 if permission else error code @@ -385,7 +385,7 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, * with a positive value. */ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, - u32 request, struct common_audit_data *sa, + u32 request, struct apparmor_audit_data *ad, void (*cb)(struct audit_buffer *, void *)) { int type, error; @@ -394,7 +394,7 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, if (likely(!denied)) { /* mask off perms that are not being force audited */ request &= perms->audit; - if (!request || !sa) + if (!request || !ad) return 0; type = AUDIT_APPARMOR_AUDIT; @@ -413,16 +413,16 @@ int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, error = -ENOENT; denied &= ~perms->quiet; - if (!sa || !denied) + if (!ad || !denied) return error; } - if (sa) { - aad(sa)->label = &profile->label; - aad(sa)->request = request; - aad(sa)->denied = denied; - aad(sa)->error = error; - aa_audit_msg(type, sa, cb); + if (ad) { + ad->subj_label = &profile->label; + ad->request = request; + ad->denied = denied; + ad->error = error; + aa_audit_msg(type, ad, cb); } if (type == AUDIT_APPARMOR_ALLOWED) diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 3fa325d5efac..4981bdf02993 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -49,12 +49,19 @@ union aa_buffer { DECLARE_FLEX_ARRAY(char, buffer); }; +struct aa_local_cache { + unsigned int hold; + unsigned int count; + struct list_head head; +}; + #define RESERVE_COUNT 2 static int reserve_count = RESERVE_COUNT; static int buffer_count; static LIST_HEAD(aa_global_buffers); static DEFINE_SPINLOCK(aa_buffers_lock); +static DEFINE_PER_CPU(struct aa_local_cache, aa_local_buffers); /* * LSM hook functions @@ -116,15 +123,17 @@ static int apparmor_ptrace_access_check(struct task_struct *child, unsigned int mode) { struct aa_label *tracer, *tracee; + const struct cred *cred; int error; + cred = get_task_cred(child); + tracee = cred_label(cred); /* ref count on cred */ tracer = __begin_current_label_crit_section(); - tracee = aa_get_task_label(child); - error = aa_may_ptrace(tracer, tracee, + error = aa_may_ptrace(current_cred(), tracer, cred, tracee, (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ : AA_PTRACE_TRACE); - aa_put_label(tracee); __end_current_label_crit_section(tracer); + put_cred(cred); return error; } @@ -132,12 +141,15 @@ static int apparmor_ptrace_access_check(struct task_struct *child, static int apparmor_ptrace_traceme(struct task_struct *parent) { struct aa_label *tracer, *tracee; + const struct cred *cred; int error; tracee = __begin_current_label_crit_section(); - tracer = aa_get_task_label(parent); - error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); - aa_put_label(tracer); + cred = get_task_cred(parent); + tracer = cred_label(cred); /* ref count on cred */ + error = aa_may_ptrace(cred, tracer, current_cred(), tracee, + AA_PTRACE_TRACE); + put_cred(cred); __end_current_label_crit_section(tracee); return error; @@ -188,7 +200,7 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, label = aa_get_newest_cred_label(cred); if (!unconfined(label)) - error = aa_capable(label, cap, opts); + error = aa_capable(cred, label, cap, opts); aa_put_label(label); return error; @@ -211,7 +223,8 @@ static int common_perm(const char *op, const struct path *path, u32 mask, label = __begin_current_label_crit_section(); if (!unconfined(label)) - error = aa_path_perm(op, label, path, 0, mask, cond); + error = aa_path_perm(op, current_cred(), label, path, 0, mask, + cond); __end_current_label_crit_section(label); return error; @@ -357,7 +370,8 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_ label = begin_current_label_crit_section(); if (!unconfined(label)) - error = aa_path_link(label, old_dentry, new_dir, new_dentry); + error = aa_path_link(current_cred(), label, old_dentry, new_dir, + new_dentry); end_current_label_crit_section(label); return error; @@ -396,23 +410,27 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(old_dentry)); cond_exchange.uid = vfsuid_into_kuid(vfsuid); - error = aa_path_perm(OP_RENAME_SRC, label, &new_path, 0, + error = aa_path_perm(OP_RENAME_SRC, current_cred(), + label, &new_path, 0, MAY_READ | AA_MAY_GETATTR | MAY_WRITE | AA_MAY_SETATTR | AA_MAY_DELETE, &cond_exchange); if (!error) - error = aa_path_perm(OP_RENAME_DEST, label, &old_path, + error = aa_path_perm(OP_RENAME_DEST, current_cred(), + label, &old_path, 0, MAY_WRITE | AA_MAY_SETATTR | AA_MAY_CREATE, &cond_exchange); } if (!error) - error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, + error = aa_path_perm(OP_RENAME_SRC, current_cred(), + label, &old_path, 0, MAY_READ | AA_MAY_GETATTR | MAY_WRITE | AA_MAY_SETATTR | AA_MAY_DELETE, &cond); if (!error) - error = aa_path_perm(OP_RENAME_DEST, label, &new_path, + error = aa_path_perm(OP_RENAME_DEST, current_cred(), + label, &new_path, 0, MAY_WRITE | AA_MAY_SETATTR | AA_MAY_CREATE, &cond); @@ -467,7 +485,8 @@ static int apparmor_file_open(struct file *file) vfsuid = i_uid_into_vfsuid(idmap, inode); cond.uid = vfsuid_into_kuid(vfsuid); - error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, + error = aa_path_perm(OP_OPEN, file->f_cred, + label, &file->f_path, 0, aa_map_file_to_perms(file), &cond); /* todo cache full allowed permissions set and state */ fctx->allow = aa_map_file_to_perms(file); @@ -507,7 +526,7 @@ static int common_file_perm(const char *op, struct file *file, u32 mask, return -EACCES; label = __begin_current_label_crit_section(); - error = aa_file_perm(op, label, file, mask, in_atomic); + error = aa_file_perm(op, current_cred(), label, file, mask, in_atomic); __end_current_label_crit_section(label); return error; @@ -570,6 +589,114 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma, false); } +#ifdef CONFIG_IO_URING +static const char *audit_uring_mask(u32 mask) +{ + if (mask & AA_MAY_CREATE_SQPOLL) + return "sqpoll"; + if (mask & AA_MAY_OVERRIDE_CRED) + return "override_creds"; + return ""; +} + +static void audit_uring_cb(struct audit_buffer *ab, void *va) +{ + struct apparmor_audit_data *ad = aad_of_va(va); + + if (ad->request & AA_URING_PERM_MASK) { + audit_log_format(ab, " requested=\"%s\"", + audit_uring_mask(ad->request)); + if (ad->denied & AA_URING_PERM_MASK) { + audit_log_format(ab, " denied=\"%s\"", + audit_uring_mask(ad->denied)); + } + } + if (ad->uring.target) { + audit_log_format(ab, " tcontext="); + aa_label_xaudit(ab, labels_ns(ad->subj_label), + ad->uring.target, + FLAGS_NONE, GFP_ATOMIC); + } +} + +static int profile_uring(struct aa_profile *profile, u32 request, + struct aa_label *new, int cap, + struct apparmor_audit_data *ad) +{ + unsigned int state; + struct aa_ruleset *rules; + int error = 0; + + AA_BUG(!profile); + + rules = list_first_entry(&profile->rules, typeof(*rules), list); + state = RULE_MEDIATES(rules, AA_CLASS_IO_URING); + if (state) { + struct aa_perms perms = { }; + + if (new) { + aa_label_match(profile, rules, new, state, + false, request, &perms); + } else { + perms = *aa_lookup_perms(rules->policy, state); + } + aa_apply_modes_to_perms(profile, &perms); + error = aa_check_perms(profile, &perms, request, ad, + audit_uring_cb); + } + + return error; +} + +/** + * apparmor_uring_override_creds - check the requested cred override + * @new: the target creds + * + * Check to see if the current task is allowed to override it's credentials + * to service an io_uring operation. + */ +static int apparmor_uring_override_creds(const struct cred *new) +{ + struct aa_profile *profile; + struct aa_label *label; + int error; + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING, + OP_URING_OVERRIDE); + + ad.uring.target = cred_label(new); + label = __begin_current_label_crit_section(); + error = fn_for_each(label, profile, + profile_uring(profile, AA_MAY_OVERRIDE_CRED, + cred_label(new), CAP_SYS_ADMIN, &ad)); + __end_current_label_crit_section(label); + + return error; +} + +/** + * apparmor_uring_sqpoll - check if a io_uring polling thread can be created + * + * Check to see if the current task is allowed to create a new io_uring + * kernel polling thread. + */ +static int apparmor_uring_sqpoll(void) +{ + struct aa_profile *profile; + struct aa_label *label; + int error; + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING, + OP_URING_SQPOLL); + + label = __begin_current_label_crit_section(); + error = fn_for_each(label, profile, + profile_uring(profile, AA_MAY_CREATE_SQPOLL, + NULL, CAP_SYS_ADMIN, &ad)); + __end_current_label_crit_section(label); + + return error; +} +#endif /* CONFIG_IO_URING */ + static int apparmor_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { @@ -585,23 +712,42 @@ static int apparmor_sb_mount(const char *dev_name, const struct path *path, label = __begin_current_label_crit_section(); if (!unconfined(label)) { if (flags & MS_REMOUNT) - error = aa_remount(label, path, flags, data); + error = aa_remount(current_cred(), label, path, flags, + data); else if (flags & MS_BIND) - error = aa_bind_mount(label, path, dev_name, flags); + error = aa_bind_mount(current_cred(), label, path, + dev_name, flags); else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) - error = aa_mount_change_type(label, path, flags); + error = aa_mount_change_type(current_cred(), label, + path, flags); else if (flags & MS_MOVE) - error = aa_move_mount(label, path, dev_name); + error = aa_move_mount_old(current_cred(), label, path, + dev_name); else - error = aa_new_mount(label, dev_name, path, type, - flags, data); + error = aa_new_mount(current_cred(), label, dev_name, + path, type, flags, data); } __end_current_label_crit_section(label); return error; } +static int apparmor_move_mount(const struct path *from_path, + const struct path *to_path) +{ + struct aa_label *label; + int error = 0; + + label = __begin_current_label_crit_section(); + if (!unconfined(label)) + error = aa_move_mount(current_cred(), label, from_path, + to_path); + __end_current_label_crit_section(label); + + return error; +} + static int apparmor_sb_umount(struct vfsmount *mnt, int flags) { struct aa_label *label; @@ -609,7 +755,7 @@ static int apparmor_sb_umount(struct vfsmount *mnt, int flags) label = __begin_current_label_crit_section(); if (!unconfined(label)) - error = aa_umount(label, mnt, flags); + error = aa_umount(current_cred(), label, mnt, flags); __end_current_label_crit_section(label); return error; @@ -623,7 +769,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path, label = aa_get_current_label(); if (!unconfined(label)) - error = aa_pivotroot(label, old_path, new_path); + error = aa_pivotroot(current_cred(), label, old_path, new_path); aa_put_label(label); return error; @@ -662,7 +808,7 @@ static int apparmor_setprocattr(const char *name, void *value, char *command, *largs = NULL, *args = value; size_t arg_size; int error; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, OP_SETPROCATTR); if (size == 0) @@ -722,11 +868,11 @@ out: return error; fail: - aad(&sa)->label = begin_current_label_crit_section(); - aad(&sa)->info = name; - aad(&sa)->error = error = -EINVAL; - aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); - end_current_label_crit_section(aad(&sa)->label); + ad.subj_label = begin_current_label_crit_section(); + ad.info = name; + ad.error = error = -EINVAL; + aa_audit_msg(AUDIT_APPARMOR_DENIED, &ad, NULL); + end_current_label_crit_section(ad.subj_label); goto out; } @@ -766,9 +912,9 @@ static void apparmor_bprm_committed_creds(const struct linux_binprm *bprm) static void apparmor_current_getsecid_subj(u32 *secid) { - struct aa_label *label = aa_get_current_label(); + struct aa_label *label = __begin_current_label_crit_section(); *secid = label->secid; - aa_put_label(label); + __end_current_label_crit_section(label); } static void apparmor_task_getsecid_obj(struct task_struct *p, u32 *secid) @@ -785,7 +931,8 @@ static int apparmor_task_setrlimit(struct task_struct *task, int error = 0; if (!unconfined(label)) - error = aa_task_setrlimit(label, task, resource, new_rlim); + error = aa_task_setrlimit(current_cred(), label, task, + resource, new_rlim); __end_current_label_crit_section(label); return error; @@ -794,26 +941,48 @@ static int apparmor_task_setrlimit(struct task_struct *task, static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info, int sig, const struct cred *cred) { + const struct cred *tc; struct aa_label *cl, *tl; int error; + tc = get_task_cred(target); + tl = aa_get_newest_cred_label(tc); if (cred) { /* * Dealing with USB IO specific behavior */ cl = aa_get_newest_cred_label(cred); - tl = aa_get_task_label(target); - error = aa_may_signal(cl, tl, sig); + error = aa_may_signal(cred, cl, tc, tl, sig); aa_put_label(cl); - aa_put_label(tl); return error; + } else { + cl = __begin_current_label_crit_section(); + error = aa_may_signal(current_cred(), cl, tc, tl, sig); + __end_current_label_crit_section(cl); } - - cl = __begin_current_label_crit_section(); - tl = aa_get_task_label(target); - error = aa_may_signal(cl, tl, sig); aa_put_label(tl); - __end_current_label_crit_section(cl); + put_cred(tc); + + return error; +} + +static int apparmor_userns_create(const struct cred *cred) +{ + struct aa_label *label; + struct aa_profile *profile; + int error = 0; + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_TASK, AA_CLASS_NS, + OP_USERNS_CREATE); + + ad.subj_cred = current_cred(); + + label = begin_current_label_crit_section(); + if (!unconfined(label)) { + error = fn_for_each(label, profile, + aa_profile_ns_perm(profile, &ad, + AA_USERNS_CREATE)); + } + end_current_label_crit_section(label); return error; } @@ -829,7 +998,7 @@ static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) if (!ctx) return -ENOMEM; - SK_CTX(sk) = ctx; + sk->sk_security = ctx; return 0; } @@ -839,9 +1008,9 @@ static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) */ static void apparmor_sk_free_security(struct sock *sk) { - struct aa_sk_ctx *ctx = SK_CTX(sk); + struct aa_sk_ctx *ctx = aa_sock(sk); - SK_CTX(sk) = NULL; + sk->sk_security = NULL; aa_put_label(ctx->label); aa_put_label(ctx->peer); kfree(ctx); @@ -853,8 +1022,8 @@ static void apparmor_sk_free_security(struct sock *sk) static void apparmor_sk_clone_security(const struct sock *sk, struct sock *newsk) { - struct aa_sk_ctx *ctx = SK_CTX(sk); - struct aa_sk_ctx *new = SK_CTX(newsk); + struct aa_sk_ctx *ctx = aa_sock(sk); + struct aa_sk_ctx *new = aa_sock(newsk); if (new->label) aa_put_label(new->label); @@ -879,7 +1048,8 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern) if (!(kern || unconfined(label))) error = af_select(family, create_perm(label, family, type, protocol), - aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, + aa_af_perm(current_cred(), label, + OP_CREATE, AA_MAY_CREATE, family, type, protocol)); end_current_label_crit_section(label); @@ -907,7 +1077,7 @@ static int apparmor_socket_post_create(struct socket *sock, int family, label = aa_get_current_label(); if (sock->sk) { - struct aa_sk_ctx *ctx = SK_CTX(sock->sk); + struct aa_sk_ctx *ctx = aa_sock(sock->sk); aa_put_label(ctx->label); ctx->label = aa_get_label(label); @@ -1092,7 +1262,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) */ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { - struct aa_sk_ctx *ctx = SK_CTX(sk); + struct aa_sk_ctx *ctx = aa_sock(sk); if (!skb->secmark) return 0; @@ -1105,7 +1275,7 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) static struct aa_label *sk_peer_label(struct sock *sk) { - struct aa_sk_ctx *ctx = SK_CTX(sk); + struct aa_sk_ctx *ctx = aa_sock(sk); if (ctx->peer) return ctx->peer; @@ -1186,7 +1356,7 @@ static int apparmor_socket_getpeersec_dgram(struct socket *sock, */ static void apparmor_sock_graft(struct sock *sk, struct socket *parent) { - struct aa_sk_ctx *ctx = SK_CTX(sk); + struct aa_sk_ctx *ctx = aa_sock(sk); if (!ctx->label) ctx->label = aa_get_current_label(); @@ -1196,7 +1366,7 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent) static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { - struct aa_sk_ctx *ctx = SK_CTX(sk); + struct aa_sk_ctx *ctx = aa_sock(sk); if (!skb->secmark) return 0; @@ -1221,6 +1391,7 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = { LSM_HOOK_INIT(capget, apparmor_capget), LSM_HOOK_INIT(capable, apparmor_capable), + LSM_HOOK_INIT(move_mount, apparmor_move_mount), LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot), @@ -1294,6 +1465,7 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = { LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid_obj), LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), LSM_HOOK_INIT(task_kill, apparmor_task_kill), + LSM_HOOK_INIT(userns_create, apparmor_userns_create), #ifdef CONFIG_AUDIT LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init), @@ -1305,6 +1477,11 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = { LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx), LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid), LSM_HOOK_INIT(release_secctx, apparmor_release_secctx), + +#ifdef CONFIG_IO_URING + LSM_HOOK_INIT(uring_override_creds, apparmor_uring_override_creds), + LSM_HOOK_INIT(uring_sqpoll, apparmor_uring_sqpoll), +#endif }; /* @@ -1635,11 +1812,32 @@ static int param_set_mode(const char *val, const struct kernel_param *kp) char *aa_get_buffer(bool in_atomic) { union aa_buffer *aa_buf; + struct aa_local_cache *cache; bool try_again = true; gfp_t flags = (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); + /* use per cpu cached buffers first */ + cache = get_cpu_ptr(&aa_local_buffers); + if (!list_empty(&cache->head)) { + aa_buf = list_first_entry(&cache->head, union aa_buffer, list); + list_del(&aa_buf->list); + cache->hold--; + cache->count--; + put_cpu_ptr(&aa_local_buffers); + return &aa_buf->buffer[0]; + } + put_cpu_ptr(&aa_local_buffers); + + if (!spin_trylock(&aa_buffers_lock)) { + cache = get_cpu_ptr(&aa_local_buffers); + cache->hold += 1; + put_cpu_ptr(&aa_local_buffers); + spin_lock(&aa_buffers_lock); + } else { + cache = get_cpu_ptr(&aa_local_buffers); + put_cpu_ptr(&aa_local_buffers); + } retry: - spin_lock(&aa_buffers_lock); if (buffer_count > reserve_count || (in_atomic && !list_empty(&aa_global_buffers))) { aa_buf = list_first_entry(&aa_global_buffers, union aa_buffer, @@ -1665,6 +1863,7 @@ retry: if (!aa_buf) { if (try_again) { try_again = false; + spin_lock(&aa_buffers_lock); goto retry; } pr_warn_once("AppArmor: Failed to allocate a memory buffer.\n"); @@ -1676,15 +1875,34 @@ retry: void aa_put_buffer(char *buf) { union aa_buffer *aa_buf; + struct aa_local_cache *cache; if (!buf) return; aa_buf = container_of(buf, union aa_buffer, buffer[0]); - spin_lock(&aa_buffers_lock); - list_add(&aa_buf->list, &aa_global_buffers); - buffer_count++; - spin_unlock(&aa_buffers_lock); + cache = get_cpu_ptr(&aa_local_buffers); + if (!cache->hold) { + put_cpu_ptr(&aa_local_buffers); + + if (spin_trylock(&aa_buffers_lock)) { + /* put back on global list */ + list_add(&aa_buf->list, &aa_global_buffers); + buffer_count++; + spin_unlock(&aa_buffers_lock); + cache = get_cpu_ptr(&aa_local_buffers); + put_cpu_ptr(&aa_local_buffers); + return; + } + /* contention on global list, fallback to percpu */ + cache = get_cpu_ptr(&aa_local_buffers); + cache->hold += 1; + } + + /* cache in percpu list */ + list_add(&aa_buf->list, &cache->head); + cache->count++; + put_cpu_ptr(&aa_local_buffers); } /* @@ -1726,6 +1944,15 @@ static int __init alloc_buffers(void) union aa_buffer *aa_buf; int i, num; + /* + * per cpu set of cached allocated buffers used to help reduce + * lock contention + */ + for_each_possible_cpu(i) { + per_cpu(aa_local_buffers, i).hold = 0; + per_cpu(aa_local_buffers, i).count = 0; + INIT_LIST_HEAD(&per_cpu(aa_local_buffers, i).head); + } /* * A function may require two buffers at once. Usually the buffers are * used for a short period of time and are shared. On UP kernel buffers @@ -1765,6 +1992,7 @@ static int apparmor_dointvec(struct ctl_table *table, int write, } static struct ctl_table apparmor_sysctl_table[] = { +#ifdef CONFIG_USER_NS { .procname = "unprivileged_userns_apparmor_policy", .data = &unprivileged_userns_apparmor_policy, @@ -1772,6 +2000,7 @@ static struct ctl_table apparmor_sysctl_table[] = { .mode = 0600, .proc_handler = apparmor_dointvec, }, +#endif /* CONFIG_USER_NS */ { .procname = "apparmor_display_secid_mode", .data = &apparmor_display_secid_mode, @@ -1779,7 +2008,13 @@ static struct ctl_table apparmor_sysctl_table[] = { .mode = 0600, .proc_handler = apparmor_dointvec, }, - + { + .procname = "apparmor_restrict_unprivileged_unconfined", + .data = &aa_unprivileged_unconfined_restricted, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = apparmor_dointvec, + }, { } }; @@ -1809,7 +2044,7 @@ static unsigned int apparmor_ip_postroute(void *priv, if (sk == NULL) return NF_ACCEPT; - ctx = SK_CTX(sk); + ctx = aa_sock(sk); if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND, skb->secmark, sk)) return NF_ACCEPT; @@ -1868,6 +2103,69 @@ static int __init apparmor_nf_ip_init(void) __initcall(apparmor_nf_ip_init); #endif +static char nulldfa_src[] = { + #include "nulldfa.in" +}; +struct aa_dfa *nulldfa; + +static char stacksplitdfa_src[] = { + #include "stacksplitdfa.in" +}; +struct aa_dfa *stacksplitdfa; +struct aa_policydb *nullpdb; + +static int __init aa_setup_dfa_engine(void) +{ + int error = -ENOMEM; + + nullpdb = aa_alloc_pdb(GFP_KERNEL); + if (!nullpdb) + return -ENOMEM; + + nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), + TO_ACCEPT1_FLAG(YYTD_DATA32) | + TO_ACCEPT2_FLAG(YYTD_DATA32)); + if (IS_ERR(nulldfa)) { + error = PTR_ERR(nulldfa); + goto fail; + } + nullpdb->dfa = aa_get_dfa(nulldfa); + nullpdb->perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); + if (!nullpdb->perms) + goto fail; + nullpdb->size = 2; + + stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, + sizeof(stacksplitdfa_src), + TO_ACCEPT1_FLAG(YYTD_DATA32) | + TO_ACCEPT2_FLAG(YYTD_DATA32)); + if (IS_ERR(stacksplitdfa)) { + error = PTR_ERR(stacksplitdfa); + goto fail; + } + + return 0; + +fail: + aa_put_pdb(nullpdb); + aa_put_dfa(nulldfa); + nullpdb = NULL; + nulldfa = NULL; + stacksplitdfa = NULL; + + return error; +} + +static void __init aa_teardown_dfa_engine(void) +{ + aa_put_dfa(stacksplitdfa); + aa_put_dfa(nulldfa); + aa_put_pdb(nullpdb); + nullpdb = NULL; + stacksplitdfa = NULL; + nulldfa = NULL; +} + static int __init apparmor_init(void) { int error; diff --git a/security/apparmor/match.c b/security/apparmor/match.c index b97ef5e1db73..517d77d3c34c 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -21,50 +21,6 @@ #define base_idx(X) ((X) & 0xffffff) -static char nulldfa_src[] = { - #include "nulldfa.in" -}; -struct aa_dfa *nulldfa; - -static char stacksplitdfa_src[] = { - #include "stacksplitdfa.in" -}; -struct aa_dfa *stacksplitdfa; - -int __init aa_setup_dfa_engine(void) -{ - int error; - - nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src), - TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32)); - if (IS_ERR(nulldfa)) { - error = PTR_ERR(nulldfa); - nulldfa = NULL; - return error; - } - - stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src, - sizeof(stacksplitdfa_src), - TO_ACCEPT1_FLAG(YYTD_DATA32) | - TO_ACCEPT2_FLAG(YYTD_DATA32)); - if (IS_ERR(stacksplitdfa)) { - aa_put_dfa(nulldfa); - nulldfa = NULL; - error = PTR_ERR(stacksplitdfa); - stacksplitdfa = NULL; - return error; - } - - return 0; -} - -void __init aa_teardown_dfa_engine(void) -{ - aa_put_dfa(stacksplitdfa); - aa_put_dfa(nulldfa); -} - /** * unpack_table - unpack a dfa table (one of accept, default, base, next check) * @blob: data to unpack (NOT NULL) @@ -136,7 +92,7 @@ fail: /** * verify_table_headers - verify that the tables headers are as expected - * @tables - array of dfa tables to check (NOT NULL) + * @tables: array of dfa tables to check (NOT NULL) * @flags: flags controlling what type of accept table are acceptable * * Assumes dfa has gone through the first pass verification done by unpacking @@ -283,7 +239,7 @@ static void dfa_free(struct aa_dfa *dfa) /** * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa) - * @kr: kref callback for freeing of a dfa (NOT NULL) + * @kref: kref callback for freeing of a dfa (NOT NULL) */ void aa_dfa_free_kref(struct kref *kref) { diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c index cdfa430ae216..fb30204c761a 100644 --- a/security/apparmor/mount.c +++ b/security/apparmor/mount.c @@ -86,32 +86,34 @@ static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->mnt.type) { + if (ad->mnt.type) { audit_log_format(ab, " fstype="); - audit_log_untrustedstring(ab, aad(sa)->mnt.type); + audit_log_untrustedstring(ab, ad->mnt.type); } - if (aad(sa)->mnt.src_name) { + if (ad->mnt.src_name) { audit_log_format(ab, " srcname="); - audit_log_untrustedstring(ab, aad(sa)->mnt.src_name); + audit_log_untrustedstring(ab, ad->mnt.src_name); } - if (aad(sa)->mnt.trans) { + if (ad->mnt.trans) { audit_log_format(ab, " trans="); - audit_log_untrustedstring(ab, aad(sa)->mnt.trans); + audit_log_untrustedstring(ab, ad->mnt.trans); } - if (aad(sa)->mnt.flags) { + if (ad->mnt.flags) { audit_log_format(ab, " flags=\""); - audit_mnt_flags(ab, aad(sa)->mnt.flags); + audit_mnt_flags(ab, ad->mnt.flags); audit_log_format(ab, "\""); } - if (aad(sa)->mnt.data) { + if (ad->mnt.data) { audit_log_format(ab, " options="); - audit_log_untrustedstring(ab, aad(sa)->mnt.data); + audit_log_untrustedstring(ab, ad->mnt.data); } } /** * audit_mount - handle the auditing of mount operations + * @subj_cred: cred of the subject * @profile: the profile being enforced (NOT NULL) * @op: operation being mediated (NOT NULL) * @name: name of object being mediated (MAYBE NULL) @@ -127,14 +129,15 @@ static void audit_cb(struct audit_buffer *ab, void *va) * * Returns: %0 or error on failure */ -static int audit_mount(struct aa_profile *profile, const char *op, +static int audit_mount(const struct cred *subj_cred, + struct aa_profile *profile, const char *op, const char *name, const char *src_name, const char *type, const char *trans, unsigned long flags, const void *data, u32 request, struct aa_perms *perms, const char *info, int error) { int audit_type = AUDIT_APPARMOR_AUTO; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op); if (likely(!error)) { u32 mask = perms->audit; @@ -165,17 +168,18 @@ static int audit_mount(struct aa_profile *profile, const char *op, return error; } - aad(&sa)->name = name; - aad(&sa)->mnt.src_name = src_name; - aad(&sa)->mnt.type = type; - aad(&sa)->mnt.trans = trans; - aad(&sa)->mnt.flags = flags; + ad.subj_cred = subj_cred; + ad.name = name; + ad.mnt.src_name = src_name; + ad.mnt.type = type; + ad.mnt.trans = trans; + ad.mnt.flags = flags; if (data && (perms->audit & AA_AUDIT_DATA)) - aad(&sa)->mnt.data = data; - aad(&sa)->info = info; - aad(&sa)->error = error; + ad.mnt.data = data; + ad.info = info; + ad.error = error; - return aa_audit(audit_type, profile, &sa, audit_cb); + return aa_audit(audit_type, profile, &ad, audit_cb); } /** @@ -283,6 +287,7 @@ static int path_flags(struct aa_profile *profile, const struct path *path) /** * match_mnt_path_str - handle path matching for mount + * @subj_cred: cred of confined subject * @profile: the confining profile * @mntpath: for the mntpnt (NOT NULL) * @buffer: buffer to be used to lookup mntpath @@ -295,7 +300,8 @@ static int path_flags(struct aa_profile *profile, const struct path *path) * * Returns: 0 on success else error */ -static int match_mnt_path_str(struct aa_profile *profile, +static int match_mnt_path_str(const struct cred *subj_cred, + struct aa_profile *profile, const struct path *mntpath, char *buffer, const char *devname, const char *type, unsigned long flags, void *data, bool binary, @@ -326,8 +332,8 @@ static int match_mnt_path_str(struct aa_profile *profile, } error = -EACCES; - pos = do_match_mnt(&rules->policy, - rules->policy.start[AA_CLASS_MOUNT], + pos = do_match_mnt(rules->policy, + rules->policy->start[AA_CLASS_MOUNT], mntpnt, devname, type, flags, data, binary, &perms); if (pos) { info = mnt_info_table[pos]; @@ -336,12 +342,14 @@ static int match_mnt_path_str(struct aa_profile *profile, error = 0; audit: - return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL, + return audit_mount(subj_cred, profile, OP_MOUNT, mntpnt, devname, + type, NULL, flags, data, AA_MAY_MOUNT, &perms, info, error); } /** * match_mnt - handle path matching for mount + * @subj_cred: cred of the subject * @profile: the confining profile * @path: for the mntpnt (NOT NULL) * @buffer: buffer to be used to lookup mntpath @@ -354,7 +362,8 @@ audit: * * Returns: 0 on success else error */ -static int match_mnt(struct aa_profile *profile, const struct path *path, +static int match_mnt(const struct cred *subj_cred, + struct aa_profile *profile, const struct path *path, char *buffer, const struct path *devpath, char *devbuffer, const char *type, unsigned long flags, void *data, bool binary) @@ -378,11 +387,12 @@ static int match_mnt(struct aa_profile *profile, const struct path *path, devname = ERR_PTR(error); } - return match_mnt_path_str(profile, path, buffer, devname, type, flags, - data, binary, info); + return match_mnt_path_str(subj_cred, profile, path, buffer, devname, + type, flags, data, binary, info); } -int aa_remount(struct aa_label *label, const struct path *path, +int aa_remount(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, unsigned long flags, void *data) { struct aa_profile *profile; @@ -399,14 +409,16 @@ int aa_remount(struct aa_label *label, const struct path *path, if (!buffer) return -ENOMEM; error = fn_for_each_confined(label, profile, - match_mnt(profile, path, buffer, NULL, NULL, NULL, + match_mnt(subj_cred, profile, path, buffer, NULL, + NULL, NULL, flags, data, binary)); aa_put_buffer(buffer); return error; } -int aa_bind_mount(struct aa_label *label, const struct path *path, +int aa_bind_mount(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, const char *dev_name, unsigned long flags) { struct aa_profile *profile; @@ -433,8 +445,8 @@ int aa_bind_mount(struct aa_label *label, const struct path *path, goto out; error = fn_for_each_confined(label, profile, - match_mnt(profile, path, buffer, &old_path, old_buffer, - NULL, flags, NULL, false)); + match_mnt(subj_cred, profile, path, buffer, &old_path, + old_buffer, NULL, flags, NULL, false)); out: aa_put_buffer(buffer); aa_put_buffer(old_buffer); @@ -443,7 +455,8 @@ out: return error; } -int aa_mount_change_type(struct aa_label *label, const struct path *path, +int aa_mount_change_type(const struct cred *subj_cred, + struct aa_label *label, const struct path *path, unsigned long flags) { struct aa_profile *profile; @@ -461,50 +474,63 @@ int aa_mount_change_type(struct aa_label *label, const struct path *path, if (!buffer) return -ENOMEM; error = fn_for_each_confined(label, profile, - match_mnt(profile, path, buffer, NULL, NULL, NULL, + match_mnt(subj_cred, profile, path, buffer, NULL, + NULL, NULL, flags, NULL, false)); aa_put_buffer(buffer); return error; } -int aa_move_mount(struct aa_label *label, const struct path *path, - const char *orig_name) +int aa_move_mount(const struct cred *subj_cred, + struct aa_label *label, const struct path *from_path, + const struct path *to_path) { struct aa_profile *profile; - char *buffer = NULL, *old_buffer = NULL; - struct path old_path; + char *to_buffer = NULL, *from_buffer = NULL; int error; AA_BUG(!label); - AA_BUG(!path); + AA_BUG(!from_path); + AA_BUG(!to_path); + + to_buffer = aa_get_buffer(false); + from_buffer = aa_get_buffer(false); + error = -ENOMEM; + if (!to_buffer || !from_buffer) + goto out; + error = fn_for_each_confined(label, profile, + match_mnt(subj_cred, profile, to_path, to_buffer, + from_path, from_buffer, + NULL, MS_MOVE, NULL, false)); +out: + aa_put_buffer(to_buffer); + aa_put_buffer(from_buffer); + + return error; +} + +int aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label, + const struct path *path, const char *orig_name) +{ + struct path old_path; + int error; if (!orig_name || !*orig_name) return -EINVAL; - error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); if (error) return error; - buffer = aa_get_buffer(false); - old_buffer = aa_get_buffer(false); - error = -ENOMEM; - if (!buffer || !old_buffer) - goto out; - error = fn_for_each_confined(label, profile, - match_mnt(profile, path, buffer, &old_path, old_buffer, - NULL, MS_MOVE, NULL, false)); -out: - aa_put_buffer(buffer); - aa_put_buffer(old_buffer); + error = aa_move_mount(subj_cred, label, &old_path, path); path_put(&old_path); return error; } -int aa_new_mount(struct aa_label *label, const char *dev_name, - const struct path *path, const char *type, unsigned long flags, - void *data) +int aa_new_mount(const struct cred *subj_cred, struct aa_label *label, + const char *dev_name, const struct path *path, + const char *type, unsigned long flags, void *data) { struct aa_profile *profile; char *buffer = NULL, *dev_buffer = NULL; @@ -549,12 +575,14 @@ int aa_new_mount(struct aa_label *label, const char *dev_name, goto out; } error = fn_for_each_confined(label, profile, - match_mnt(profile, path, buffer, dev_path, dev_buffer, + match_mnt(subj_cred, profile, path, buffer, + dev_path, dev_buffer, type, flags, data, binary)); } else { error = fn_for_each_confined(label, profile, - match_mnt_path_str(profile, path, buffer, dev_name, - type, flags, data, binary, NULL)); + match_mnt_path_str(subj_cred, profile, path, + buffer, dev_name, + type, flags, data, binary, NULL)); } out: @@ -566,7 +594,8 @@ out: return error; } -static int profile_umount(struct aa_profile *profile, const struct path *path, +static int profile_umount(const struct cred *subj_cred, + struct aa_profile *profile, const struct path *path, char *buffer) { struct aa_ruleset *rules = list_first_entry(&profile->rules, @@ -587,19 +616,21 @@ static int profile_umount(struct aa_profile *profile, const struct path *path, if (error) goto audit; - state = aa_dfa_match(rules->policy.dfa, - rules->policy.start[AA_CLASS_MOUNT], + state = aa_dfa_match(rules->policy->dfa, + rules->policy->start[AA_CLASS_MOUNT], name); - perms = *aa_lookup_perms(&rules->policy, state); + perms = *aa_lookup_perms(rules->policy, state); if (AA_MAY_UMOUNT & ~perms.allow) error = -EACCES; audit: - return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL, + return audit_mount(subj_cred, profile, OP_UMOUNT, name, NULL, NULL, + NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error); } -int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) +int aa_umount(const struct cred *subj_cred, struct aa_label *label, + struct vfsmount *mnt, int flags) { struct aa_profile *profile; char *buffer = NULL; @@ -614,7 +645,7 @@ int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) return -ENOMEM; error = fn_for_each_confined(label, profile, - profile_umount(profile, &path, buffer)); + profile_umount(subj_cred, profile, &path, buffer)); aa_put_buffer(buffer); return error; @@ -624,7 +655,8 @@ int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) * * Returns: label for transition or ERR_PTR. Does not return NULL */ -static struct aa_label *build_pivotroot(struct aa_profile *profile, +static struct aa_label *build_pivotroot(const struct cred *subj_cred, + struct aa_profile *profile, const struct path *new_path, char *new_buffer, const struct path *old_path, @@ -658,18 +690,19 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile, goto audit; error = -EACCES; - state = aa_dfa_match(rules->policy.dfa, - rules->policy.start[AA_CLASS_MOUNT], + state = aa_dfa_match(rules->policy->dfa, + rules->policy->start[AA_CLASS_MOUNT], new_name); - state = aa_dfa_null_transition(rules->policy.dfa, state); - state = aa_dfa_match(rules->policy.dfa, state, old_name); - perms = *aa_lookup_perms(&rules->policy, state); + state = aa_dfa_null_transition(rules->policy->dfa, state); + state = aa_dfa_match(rules->policy->dfa, state, old_name); + perms = *aa_lookup_perms(rules->policy, state); if (AA_MAY_PIVOTROOT & perms.allow) error = 0; audit: - error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name, + error = audit_mount(subj_cred, profile, OP_PIVOTROOT, new_name, + old_name, NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT, &perms, info, error); if (error) @@ -678,7 +711,8 @@ audit: return aa_get_newest_label(&profile->label); } -int aa_pivotroot(struct aa_label *label, const struct path *old_path, +int aa_pivotroot(const struct cred *subj_cred, struct aa_label *label, + const struct path *old_path, const struct path *new_path) { struct aa_profile *profile; @@ -696,7 +730,8 @@ int aa_pivotroot(struct aa_label *label, const struct path *old_path, if (!old_buffer || !new_buffer) goto out; target = fn_label_build(label, profile, GFP_KERNEL, - build_pivotroot(profile, new_path, new_buffer, + build_pivotroot(subj_cred, profile, new_path, + new_buffer, old_path, old_buffer)); if (!target) { info = "label build failed"; @@ -722,7 +757,8 @@ out: fail: /* TODO: add back in auditing of new_name and old_name */ error = fn_for_each(label, profile, - audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */, + audit_mount(subj_cred, profile, OP_PIVOTROOT, + NULL /*new_name */, NULL /* old_name */, NULL, NULL, 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info, diff --git a/security/apparmor/net.c b/security/apparmor/net.c index 788be1609a86..87e934b2b548 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c @@ -71,6 +71,7 @@ static const char * const net_mask_names[] = { void audit_net_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); if (address_family_names[sa->u.net->family]) audit_log_format(ab, " family=\"%s\"", @@ -78,35 +79,36 @@ void audit_net_cb(struct audit_buffer *ab, void *va) else audit_log_format(ab, " family=\"unknown(%d)\"", sa->u.net->family); - if (sock_type_names[aad(sa)->net.type]) + if (sock_type_names[ad->net.type]) audit_log_format(ab, " sock_type=\"%s\"", - sock_type_names[aad(sa)->net.type]); + sock_type_names[ad->net.type]); else audit_log_format(ab, " sock_type=\"unknown(%d)\"", - aad(sa)->net.type); - audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol); + ad->net.type); + audit_log_format(ab, " protocol=%d", ad->net.protocol); - if (aad(sa)->request & NET_PERMS_MASK) { + if (ad->request & NET_PERMS_MASK) { audit_log_format(ab, " requested_mask="); - aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0, + aa_audit_perm_mask(ab, ad->request, NULL, 0, net_mask_names, NET_PERMS_MASK); - if (aad(sa)->denied & NET_PERMS_MASK) { + if (ad->denied & NET_PERMS_MASK) { audit_log_format(ab, " denied_mask="); - aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0, + aa_audit_perm_mask(ab, ad->denied, NULL, 0, net_mask_names, NET_PERMS_MASK); } } - if (aad(sa)->peer) { + if (ad->peer) { audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } } /* Generic af perm */ -int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, - u32 request, u16 family, int type) +int aa_profile_af_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, u32 request, u16 family, + int type) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); @@ -125,26 +127,28 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, buffer[0] = cpu_to_be16(family); buffer[1] = cpu_to_be16((u16) type); - state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, + state = aa_dfa_match_len(rules->policy->dfa, state, (char *) &buffer, 4); - perms = *aa_lookup_perms(&rules->policy, state); + perms = *aa_lookup_perms(rules->policy, state); aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_net_cb); + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); } -int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, - int type, int protocol) +int aa_af_perm(const struct cred *subj_cred, struct aa_label *label, + const char *op, u32 request, u16 family, int type, int protocol) { struct aa_profile *profile; - DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol); + DEFINE_AUDIT_NET(ad, op, NULL, family, type, protocol); return fn_for_each_confined(label, profile, - aa_profile_af_perm(profile, &sa, request, family, + aa_profile_af_perm(profile, &ad, request, family, type)); } -static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, +static int aa_label_sk_perm(const struct cred *subj_cred, + struct aa_label *label, + const char *op, u32 request, struct sock *sk) { struct aa_sk_ctx *ctx = SK_CTX(sk); @@ -155,10 +159,11 @@ static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, if (ctx->label != kernel_t && !unconfined(label)) { struct aa_profile *profile; - DEFINE_AUDIT_SK(sa, op, sk); + DEFINE_AUDIT_SK(ad, op, sk); + ad.subj_cred = subj_cred; error = fn_for_each_confined(label, profile, - aa_profile_af_sk_perm(profile, &sa, request, sk)); + aa_profile_af_sk_perm(profile, &ad, request, sk)); } return error; @@ -174,21 +179,21 @@ int aa_sk_perm(const char *op, u32 request, struct sock *sk) /* TODO: switch to begin_current_label ???? */ label = begin_current_label_crit_section(); - error = aa_label_sk_perm(label, op, request, sk); + error = aa_label_sk_perm(current_cred(), label, op, request, sk); end_current_label_crit_section(label); return error; } -int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, - struct socket *sock) +int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label, + const char *op, u32 request, struct socket *sock) { AA_BUG(!label); AA_BUG(!sock); AA_BUG(!sock->sk); - return aa_label_sk_perm(label, op, request, sock->sk); + return aa_label_sk_perm(subj_cred, label, op, request, sock->sk); } #ifdef CONFIG_NETWORK_SECMARK @@ -214,7 +219,7 @@ static int apparmor_secmark_init(struct aa_secmark *secmark) } static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { int i, ret; struct aa_perms perms = { }; @@ -245,17 +250,17 @@ static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_net_cb); + return aa_check_perms(profile, &perms, request, ad, audit_net_cb); } int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, u32 secid, const struct sock *sk) { struct aa_profile *profile; - DEFINE_AUDIT_SK(sa, op, sk); + DEFINE_AUDIT_SK(ad, op, sk); return fn_for_each_confined(label, profile, aa_secmark_perm(profile, request, secid, - &sa)); + &ad)); } #endif diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index b38f7b2a5e1d..ed4c9803c8fa 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -88,6 +88,7 @@ #include "include/resource.h" int unprivileged_userns_apparmor_policy = 1; +int aa_unprivileged_unconfined_restricted; const char *const aa_profile_mode_names[] = { "enforce", @@ -98,6 +99,41 @@ const char *const aa_profile_mode_names[] = { }; +static void aa_free_pdb(struct aa_policydb *policy) +{ + if (policy) { + aa_put_dfa(policy->dfa); + if (policy->perms) + kvfree(policy->perms); + aa_free_str_table(&policy->trans); + } +} + +/** + * aa_pdb_free_kref - free aa_policydb by kref (called by aa_put_pdb) + * @kref: kref callback for freeing of a dfa (NOT NULL) + */ +void aa_pdb_free_kref(struct kref *kref) +{ + struct aa_policydb *pdb = container_of(kref, struct aa_policydb, count); + + aa_free_pdb(pdb); +} + + +struct aa_policydb *aa_alloc_pdb(gfp_t gfp) +{ + struct aa_policydb *pdb = kzalloc(sizeof(struct aa_policydb), gfp); + + if (!pdb) + return NULL; + + kref_init(&pdb->count); + + return pdb; +} + + /** * __add_profile - add a profiles to list and label tree * @list: list to add it to (NOT NULL) @@ -200,15 +236,15 @@ static void free_attachment(struct aa_attachment *attach) for (i = 0; i < attach->xattr_count; i++) kfree_sensitive(attach->xattrs[i]); kfree_sensitive(attach->xattrs); - aa_destroy_policydb(&attach->xmatch); + aa_put_pdb(attach->xmatch); } static void free_ruleset(struct aa_ruleset *rules) { int i; - aa_destroy_policydb(&rules->file); - aa_destroy_policydb(&rules->policy); + aa_put_pdb(rules->file); + aa_put_pdb(rules->policy); aa_free_cap_rules(&rules->caps); aa_free_rlimit_rules(&rules->rlimits); @@ -255,6 +291,7 @@ void aa_free_profile(struct aa_profile *profile) aa_put_ns(profile->ns); kfree_sensitive(profile->rename); + kfree_sensitive(profile->disconnected); free_attachment(&profile->attach); @@ -285,6 +322,7 @@ void aa_free_profile(struct aa_profile *profile) /** * aa_alloc_profile - allocate, initialize and return a new profile * @hname: name of the profile (NOT NULL) + * @proxy: proxy to use OR null if to allocate a new one * @gfp: allocation type * * Returns: refcount profile or NULL on failure @@ -588,16 +626,8 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, /* TODO: ideally we should inherit abi from parent */ profile->label.flags |= FLAG_NULL; rules = list_first_entry(&profile->rules, typeof(*rules), list); - rules->file.dfa = aa_get_dfa(nulldfa); - rules->file.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); - if (!rules->file.perms) - goto fail; - rules->file.size = 2; - rules->policy.dfa = aa_get_dfa(nulldfa); - rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), GFP_KERNEL); - if (!rules->policy.perms) - goto fail; - rules->policy.size = 2; + rules->file = aa_get_pdb(nullpdb); + rules->policy = aa_get_pdb(nullpdb); if (parent) { profile->path_flags = parent->path_flags; @@ -608,11 +638,6 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, } return profile; - -fail: - aa_free_profile(profile); - - return NULL; } /** @@ -721,16 +746,17 @@ static int replacement_allowed(struct aa_profile *profile, int noreplace, static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->iface.ns) { + if (ad->iface.ns) { audit_log_format(ab, " ns="); - audit_log_untrustedstring(ab, aad(sa)->iface.ns); + audit_log_untrustedstring(ab, ad->iface.ns); } } /** * audit_policy - Do auditing of policy changes - * @label: label to check if it can manage policy + * @subj_label: label to check if it can manage policy * @op: policy operation being performed * @ns_name: name of namespace being manipulated * @name: name of profile being manipulated (NOT NULL) @@ -739,19 +765,19 @@ static void audit_cb(struct audit_buffer *ab, void *va) * * Returns: the error to be returned after audit is done */ -static int audit_policy(struct aa_label *label, const char *op, +static int audit_policy(struct aa_label *subj_label, const char *op, const char *ns_name, const char *name, const char *info, int error) { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, op); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, op); - aad(&sa)->iface.ns = ns_name; - aad(&sa)->name = name; - aad(&sa)->info = info; - aad(&sa)->error = error; - aad(&sa)->label = label; + ad.iface.ns = ns_name; + ad.name = name; + ad.info = info; + ad.error = error; + ad.subj_label = subj_label; - aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb); + aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, audit_cb); return error; } @@ -759,31 +785,35 @@ static int audit_policy(struct aa_label *label, const char *op, /* don't call out to other LSMs in the stack for apparmor policy admin * permissions */ -static int policy_ns_capable(struct aa_label *label, +static int policy_ns_capable(const struct cred *subj_cred, + struct aa_label *label, struct user_namespace *userns, int cap) { int err; /* check for MAC_ADMIN cap in cred */ - err = cap_capable(current_cred(), userns, cap, CAP_OPT_NONE); + err = cap_capable(subj_cred, userns, cap, CAP_OPT_NONE); if (!err) - err = aa_capable(label, cap, CAP_OPT_NONE); + err = aa_capable(subj_cred, label, cap, CAP_OPT_NONE); return err; } /** * aa_policy_view_capable - check if viewing policy in at @ns is allowed - * label: label that is trying to view policy in ns - * ns: namespace being viewed by @label (may be NULL if @label's ns) + * @subj_cred: cred of subject + * @label: label that is trying to view policy in ns + * @ns: namespace being viewed by @label (may be NULL if @label's ns) + * * Returns: true if viewing policy is allowed * * If @ns is NULL then the namespace being viewed is assumed to be the * tasks current namespace. */ -bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) +bool aa_policy_view_capable(const struct cred *subj_cred, + struct aa_label *label, struct aa_ns *ns) { - struct user_namespace *user_ns = current_user_ns(); + struct user_namespace *user_ns = subj_cred->user_ns; struct aa_ns *view_ns = labels_view(label); bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) || in_egroup_p(make_kgid(user_ns, 0)); @@ -800,15 +830,17 @@ bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns) return response; } -bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns) +bool aa_policy_admin_capable(const struct cred *subj_cred, + struct aa_label *label, struct aa_ns *ns) { - struct user_namespace *user_ns = current_user_ns(); - bool capable = policy_ns_capable(label, user_ns, CAP_MAC_ADMIN) == 0; + struct user_namespace *user_ns = subj_cred->user_ns; + bool capable = policy_ns_capable(subj_cred, label, user_ns, + CAP_MAC_ADMIN) == 0; AA_DEBUG("cap_mac_admin? %d\n", capable); AA_DEBUG("policy locked? %d\n", aa_g_lock_policy); - return aa_policy_view_capable(label, ns) && capable && + return aa_policy_view_capable(subj_cred, label, ns) && capable && !aa_g_lock_policy; } @@ -818,7 +850,7 @@ bool aa_current_policy_view_capable(struct aa_ns *ns) bool res; label = __begin_current_label_crit_section(); - res = aa_policy_view_capable(label, ns); + res = aa_policy_view_capable(current_cred(), label, ns); __end_current_label_crit_section(label); return res; @@ -830,7 +862,7 @@ bool aa_current_policy_admin_capable(struct aa_ns *ns) bool res; label = __begin_current_label_crit_section(); - res = aa_policy_admin_capable(label, ns); + res = aa_policy_admin_capable(current_cred(), label, ns); __end_current_label_crit_section(label); return res; @@ -838,12 +870,15 @@ bool aa_current_policy_admin_capable(struct aa_ns *ns) /** * aa_may_manage_policy - can the current task manage policy + * @subj_cred: subjects cred * @label: label to check if it can manage policy + * @ns: namespace being managed by @label (may be NULL if @label's ns) * @mask: contains the policy manipulation operation being done * * Returns: 0 if the task is allowed to manipulate policy else error */ -int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) +int aa_may_manage_policy(const struct cred *subj_cred, struct aa_label *label, + struct aa_ns *ns, u32 mask) { const char *op; @@ -859,7 +894,7 @@ int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) return audit_policy(label, op, NULL, NULL, "policy_locked", -EACCES); - if (!aa_policy_admin_capable(label, ns)) + if (!aa_policy_admin_capable(subj_cred, label, ns)) return audit_policy(label, op, NULL, NULL, "not policy admin", -EACCES); @@ -950,11 +985,11 @@ static void __replace_profile(struct aa_profile *old, struct aa_profile *new) /** * __lookup_replace - lookup replacement information for a profile - * @ns - namespace the lookup occurs in - * @hname - name of profile to lookup - * @noreplace - true if not replacing an existing profile - * @p - Returns: profile to be replaced - * @info - Returns: info string on why lookup failed + * @ns: namespace the lookup occurs in + * @hname: name of profile to lookup + * @noreplace: true if not replacing an existing profile + * @p: Returns - profile to be replaced + * @info: Returns - info string on why lookup failed * * Returns: profile to replace (no ref) on success else ptr error */ diff --git a/security/apparmor/policy_compat.c b/security/apparmor/policy_compat.c index 0cb02da8a319..423227670e68 100644 --- a/security/apparmor/policy_compat.c +++ b/security/apparmor/policy_compat.c @@ -143,6 +143,7 @@ static struct aa_perms compute_fperms_other(struct aa_dfa *dfa, * compute_fperms - convert dfa compressed perms to internal perms and store * them so they can be retrieved later. * @dfa: a dfa using fperms to remap to internal permissions + * @size: Returns the permission table size * * Returns: remapped perm table */ diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c index fd5b7afbcb48..1f02cfe1d974 100644 --- a/security/apparmor/policy_ns.c +++ b/security/apparmor/policy_ns.c @@ -159,43 +159,6 @@ void aa_free_ns(struct aa_ns *ns) kfree_sensitive(ns); } -/** - * aa_findn_ns - look up a profile namespace on the namespace list - * @root: namespace to search in (NOT NULL) - * @name: name of namespace to find (NOT NULL) - * @n: length of @name - * - * Returns: a refcounted namespace on the list, or NULL if no namespace - * called @name exists. - * - * refcount released by caller - */ -struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n) -{ - struct aa_ns *ns = NULL; - - rcu_read_lock(); - ns = aa_get_ns(__aa_findn_ns(&root->sub_ns, name, n)); - rcu_read_unlock(); - - return ns; -} - -/** - * aa_find_ns - look up a profile namespace on the namespace list - * @root: namespace to search in (NOT NULL) - * @name: name of namespace to find (NOT NULL) - * - * Returns: a refcounted namespace on the list, or NULL if no namespace - * called @name exists. - * - * refcount released by caller - */ -struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) -{ - return aa_findn_ns(root, name, strlen(name)); -} - /** * __aa_lookupn_ns - lookup the namespace matching @hname * @view: namespace to search in (NOT NULL) diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 913ec8d0eb63..47ec097d6741 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -34,17 +34,18 @@ static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->iface.ns) { + if (ad->iface.ns) { audit_log_format(ab, " ns="); - audit_log_untrustedstring(ab, aad(sa)->iface.ns); + audit_log_untrustedstring(ab, ad->iface.ns); } - if (aad(sa)->name) { + if (ad->name) { audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, aad(sa)->name); + audit_log_untrustedstring(ab, ad->name); } - if (aad(sa)->iface.pos) - audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos); + if (ad->iface.pos) + audit_log_format(ab, " offset=%ld", ad->iface.pos); } /** @@ -63,18 +64,18 @@ static int audit_iface(struct aa_profile *new, const char *ns_name, int error) { struct aa_profile *profile = labels_profile(aa_current_raw_label()); - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); if (e) - aad(&sa)->iface.pos = e->pos - e->start; - aad(&sa)->iface.ns = ns_name; + ad.iface.pos = e->pos - e->start; + ad.iface.ns = ns_name; if (new) - aad(&sa)->name = new->base.hname; + ad.name = new->base.hname; else - aad(&sa)->name = name; - aad(&sa)->info = info; - aad(&sa)->error = error; + ad.name = name; + ad.info = info; + ad.error = error; - return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb); + return aa_audit(AUDIT_APPARMOR_STATUS, profile, &ad, audit_cb); } void __aa_loaddata_update(struct aa_loaddata *data, long revision) @@ -705,24 +706,29 @@ fail_reset: return -EPROTO; } -static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, +static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy, bool required_dfa, bool required_trans, const char **info) { + struct aa_policydb *pdb; void *pos = e->pos; int i, flags, error = -EPROTO; ssize_t size; - size = unpack_perms_table(e, &policy->perms); + pdb = aa_alloc_pdb(GFP_KERNEL); + if (!pdb) + return -ENOMEM; + + size = unpack_perms_table(e, &pdb->perms); if (size < 0) { error = size; - policy->perms = NULL; + pdb->perms = NULL; *info = "failed to unpack - perms"; goto fail; } - policy->size = size; + pdb->size = size; - if (policy->perms) { + if (pdb->perms) { /* perms table present accept is index */ flags = TO_ACCEPT1_FLAG(YYTD_DATA32); } else { @@ -731,13 +737,13 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, TO_ACCEPT2_FLAG(YYTD_DATA32); } - policy->dfa = unpack_dfa(e, flags); - if (IS_ERR(policy->dfa)) { - error = PTR_ERR(policy->dfa); - policy->dfa = NULL; + pdb->dfa = unpack_dfa(e, flags); + if (IS_ERR(pdb->dfa)) { + error = PTR_ERR(pdb->dfa); + pdb->dfa = NULL; *info = "failed to unpack - dfa"; goto fail; - } else if (!policy->dfa) { + } else if (!pdb->dfa) { if (required_dfa) { *info = "missing required dfa"; goto fail; @@ -751,18 +757,18 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, * sadly start was given different names for file and policydb * but since it is optional we can try both */ - if (!aa_unpack_u32(e, &policy->start[0], "start")) + if (!aa_unpack_u32(e, &pdb->start[0], "start")) /* default start state */ - policy->start[0] = DFA_START; - if (!aa_unpack_u32(e, &policy->start[AA_CLASS_FILE], "dfa_start")) { + pdb->start[0] = DFA_START; + if (!aa_unpack_u32(e, &pdb->start[AA_CLASS_FILE], "dfa_start")) { /* default start state for xmatch and file dfa */ - policy->start[AA_CLASS_FILE] = DFA_START; + pdb->start[AA_CLASS_FILE] = DFA_START; } /* setup class index */ for (i = AA_CLASS_FILE + 1; i <= AA_CLASS_LAST; i++) { - policy->start[i] = aa_dfa_next(policy->dfa, policy->start[0], + pdb->start[i] = aa_dfa_next(pdb->dfa, pdb->start[0], i); } - if (!unpack_trans_table(e, &policy->trans) && required_trans) { + if (!unpack_trans_table(e, &pdb->trans) && required_trans) { *info = "failed to unpack profile transition table"; goto fail; } @@ -770,9 +776,11 @@ static int unpack_pdb(struct aa_ext *e, struct aa_policydb *policy, /* TODO: move compat mapping here, requires dfa merging first */ /* TODO: move verify here, it has to be done after compat mappings */ out: + *policy = pdb; return 0; fail: + aa_put_pdb(pdb); e->pos = pos; return error; } @@ -807,7 +815,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) const char *info = "failed to unpack profile"; size_t ns_len; struct rhashtable_params params = { 0 }; - char *key = NULL; + char *key = NULL, *disconnected = NULL; struct aa_data *data; int error = -EPROTO; kernel_cap_t tmpcap; @@ -856,15 +864,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) } /* neither xmatch_len not xmatch_perms are optional if xmatch is set */ - if (profile->attach.xmatch.dfa) { + if (profile->attach.xmatch->dfa) { if (!aa_unpack_u32(e, &tmp, NULL)) { info = "missing xmatch len"; goto fail; } profile->attach.xmatch_len = tmp; - profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START; - if (!profile->attach.xmatch.perms) { - error = aa_compat_map_xmatch(&profile->attach.xmatch); + profile->attach.xmatch->start[AA_CLASS_XMATCH] = DFA_START; + if (!profile->attach.xmatch->perms) { + error = aa_compat_map_xmatch(profile->attach.xmatch); if (error) { info = "failed to convert xmatch permission table"; goto fail; @@ -873,7 +881,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) } /* disconnected attachment string is optional */ - (void) aa_unpack_str(e, &profile->disconnected, "disconnected"); + (void) aa_unpack_strdup(e, &disconnected, "disconnected"); + profile->disconnected = disconnected; /* per profile debug flags (complain, audit) */ if (!aa_unpack_nameX(e, AA_STRUCT, "flags")) { @@ -980,16 +989,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) if (error) goto fail; /* Fixup: drop when we get rid of start array */ - if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], + if (aa_dfa_next(rules->policy->dfa, rules->policy->start[0], AA_CLASS_FILE)) - rules->policy.start[AA_CLASS_FILE] = - aa_dfa_next(rules->policy.dfa, - rules->policy.start[0], + rules->policy->start[AA_CLASS_FILE] = + aa_dfa_next(rules->policy->dfa, + rules->policy->start[0], AA_CLASS_FILE); if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; - if (!rules->policy.perms) { - error = aa_compat_map_policy(&rules->policy, + if (!rules->policy->perms) { + error = aa_compat_map_policy(rules->policy, e->version); if (error) { info = "failed to remap policydb permission table"; @@ -997,44 +1006,25 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) } } } else { - rules->policy.dfa = aa_get_dfa(nulldfa); - rules->policy.perms = kcalloc(2, sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->policy.perms) - goto fail; - rules->policy.size = 2; + rules->policy = aa_get_pdb(nullpdb); } /* get file rules */ error = unpack_pdb(e, &rules->file, false, true, &info); if (error) { goto fail; - } else if (rules->file.dfa) { - if (!rules->file.perms) { - error = aa_compat_map_file(&rules->file); + } else if (rules->file->dfa) { + if (!rules->file->perms) { + error = aa_compat_map_file(rules->file); if (error) { info = "failed to remap file permission table"; goto fail; } } - } else if (rules->policy.dfa && - rules->policy.start[AA_CLASS_FILE]) { - rules->file.dfa = aa_get_dfa(rules->policy.dfa); - rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE]; - rules->file.perms = kcalloc(rules->policy.size, - sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->file.perms) - goto fail; - memcpy(rules->file.perms, rules->policy.perms, - rules->policy.size * sizeof(struct aa_perms)); - rules->file.size = rules->policy.size; + } else if (rules->policy->dfa && + rules->policy->start[AA_CLASS_FILE]) { + rules->file = aa_get_pdb(rules->policy); } else { - rules->file.dfa = aa_get_dfa(nulldfa); - rules->file.perms = kcalloc(2, sizeof(struct aa_perms), - GFP_KERNEL); - if (!rules->file.perms) - goto fail; - rules->file.size = 2; + rules->file = aa_get_pdb(nullpdb); } error = -EPROTO; if (aa_unpack_nameX(e, AA_STRUCT, "data")) { @@ -1170,7 +1160,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns) /** * verify_dfa_accept_index - verify accept indexes are in range of perms table * @dfa: the dfa to check accept indexes are in range - * table_size: the permission table size the indexes should be within + * @table_size: the permission table size the indexes should be within */ static bool verify_dfa_accept_index(struct aa_dfa *dfa, int table_size) { @@ -1241,26 +1231,32 @@ static int verify_profile(struct aa_profile *profile) if (!rules) return 0; - if ((rules->file.dfa && !verify_dfa_accept_index(rules->file.dfa, - rules->file.size)) || - (rules->policy.dfa && - !verify_dfa_accept_index(rules->policy.dfa, rules->policy.size))) { + if (rules->file->dfa && !verify_dfa_accept_index(rules->file->dfa, + rules->file->size)) { audit_iface(profile, NULL, NULL, - "Unpack: Invalid named transition", NULL, -EPROTO); + "Unpack: file Invalid named transition", NULL, + -EPROTO); + return -EPROTO; + } + if (rules->policy->dfa && + !verify_dfa_accept_index(rules->policy->dfa, rules->policy->size)) { + audit_iface(profile, NULL, NULL, + "Unpack: policy Invalid named transition", NULL, + -EPROTO); return -EPROTO; } - if (!verify_perms(&rules->file)) { + if (!verify_perms(rules->file)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&rules->policy)) { + if (!verify_perms(rules->policy)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; } - if (!verify_perms(&profile->attach.xmatch)) { + if (!verify_perms(profile->attach.xmatch)) { audit_iface(profile, NULL, NULL, "Unpack: Invalid perm index", NULL, -EPROTO); return -EPROTO; diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index e85948164896..dcc94c3153d5 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c @@ -30,18 +30,20 @@ struct aa_sfs_entry aa_sfs_entry_rlimit[] = { static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); audit_log_format(ab, " rlimit=%s value=%lu", - rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max); - if (aad(sa)->peer) { + rlim_names[ad->rlim.rlim], ad->rlim.max); + if (ad->peer) { audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } } /** * audit_resource - audit setting resource limit + * @subj_cred: cred setting the resource * @profile: profile being enforced (NOT NULL) * @resource: rlimit being auditing * @value: value being set @@ -49,22 +51,24 @@ static void audit_cb(struct audit_buffer *ab, void *va) * @info: info being auditing * @error: error value * - * Returns: 0 or sa->error else other error code on failure + * Returns: 0 or ad->error else other error code on failure */ -static int audit_resource(struct aa_profile *profile, unsigned int resource, +static int audit_resource(const struct cred *subj_cred, + struct aa_profile *profile, unsigned int resource, unsigned long value, struct aa_label *peer, const char *info, int error) { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_RLIMITS, OP_SETRLIMIT); - aad(&sa)->rlim.rlim = resource; - aad(&sa)->rlim.max = value; - aad(&sa)->peer = peer; - aad(&sa)->info = info; - aad(&sa)->error = error; + ad.subj_cred = subj_cred; + ad.rlim.rlim = resource; + ad.rlim.max = value; + ad.peer = peer; + ad.info = info; + ad.error = error; - return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb); + return aa_audit(AUDIT_APPARMOR_AUTO, profile, &ad, audit_cb); } /** @@ -81,7 +85,8 @@ int aa_map_resource(int resource) return rlim_map[resource]; } -static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, +static int profile_setrlimit(const struct cred *subj_cred, + struct aa_profile *profile, unsigned int resource, struct rlimit *new_rlim) { struct aa_ruleset *rules = list_first_entry(&profile->rules, @@ -91,22 +96,24 @@ static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max > rules->rlimits.limits[resource].rlim_max) e = -EACCES; - return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL, - e); + return audit_resource(subj_cred, profile, resource, new_rlim->rlim_max, + NULL, NULL, e); } /** * aa_task_setrlimit - test permission to set an rlimit - * @label - label confining the task (NOT NULL) - * @task - task the resource is being set on - * @resource - the resource being set - * @new_rlim - the new resource limit (NOT NULL) + * @subj_cred: cred setting the limit + * @label: label confining the task (NOT NULL) + * @task: task the resource is being set on + * @resource: the resource being set + * @new_rlim: the new resource limit (NOT NULL) * * Control raising the processes hard limit. * * Returns: 0 or error code if setting resource failed */ -int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, +int aa_task_setrlimit(const struct cred *subj_cred, struct aa_label *label, + struct task_struct *task, unsigned int resource, struct rlimit *new_rlim) { struct aa_profile *profile; @@ -125,14 +132,15 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, */ if (label != peer && - aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0) + aa_capable(subj_cred, label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0) error = fn_for_each(label, profile, - audit_resource(profile, resource, + audit_resource(subj_cred, profile, resource, new_rlim->rlim_max, peer, "cap_sys_resource", -EACCES)); else error = fn_for_each_confined(label, profile, - profile_setrlimit(profile, resource, new_rlim)); + profile_setrlimit(subj_cred, profile, resource, + new_rlim)); aa_put_label(peer); return error; diff --git a/security/apparmor/task.c b/security/apparmor/task.c index 84d16a29bfcb..f29a2e80e6bf 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c @@ -93,9 +93,8 @@ int aa_replace_current_label(struct aa_label *label) * aa_set_current_onexec - set the tasks change_profile to happen onexec * @label: system label to set at exec (MAYBE NULL to clear value) * @stack: whether stacking should be done - * Returns: 0 or error on failure */ -int aa_set_current_onexec(struct aa_label *label, bool stack) +void aa_set_current_onexec(struct aa_label *label, bool stack) { struct aa_task_ctx *ctx = task_ctx(current); @@ -103,8 +102,6 @@ int aa_set_current_onexec(struct aa_label *label, bool stack) aa_put_label(ctx->onexec); ctx->onexec = label; ctx->token = stack; - - return 0; } /** @@ -208,70 +205,75 @@ static const char *audit_ptrace_mask(u32 mask) static void audit_ptrace_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; + struct apparmor_audit_data *ad = aad(sa); - if (aad(sa)->request & AA_PTRACE_PERM_MASK) { + if (ad->request & AA_PTRACE_PERM_MASK) { audit_log_format(ab, " requested_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->request)); + audit_ptrace_mask(ad->request)); - if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { + if (ad->denied & AA_PTRACE_PERM_MASK) { audit_log_format(ab, " denied_mask=\"%s\"", - audit_ptrace_mask(aad(sa)->denied)); + audit_ptrace_mask(ad->denied)); } } audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, + aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer, FLAGS_NONE, GFP_ATOMIC); } /* assumes check for RULE_MEDIATES is already done */ /* TODO: conditionals */ -static int profile_ptrace_perm(struct aa_profile *profile, - struct aa_label *peer, u32 request, - struct common_audit_data *sa) +static int profile_ptrace_perm(const struct cred *cred, + struct aa_profile *profile, + struct aa_label *peer, u32 request, + struct apparmor_audit_data *ad) { struct aa_ruleset *rules = list_first_entry(&profile->rules, typeof(*rules), list); struct aa_perms perms = { }; - aad(sa)->peer = peer; + ad->subj_cred = cred; + ad->peer = peer; aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request, &perms); aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); + return aa_check_perms(profile, &perms, request, ad, audit_ptrace_cb); } -static int profile_tracee_perm(struct aa_profile *tracee, +static int profile_tracee_perm(const struct cred *cred, + struct aa_profile *tracee, struct aa_label *tracer, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { if (profile_unconfined(tracee) || unconfined(tracer) || !ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) return 0; - return profile_ptrace_perm(tracee, tracer, request, sa); + return profile_ptrace_perm(cred, tracee, tracer, request, ad); } -static int profile_tracer_perm(struct aa_profile *tracer, +static int profile_tracer_perm(const struct cred *cred, + struct aa_profile *tracer, struct aa_label *tracee, u32 request, - struct common_audit_data *sa) + struct apparmor_audit_data *ad) { if (profile_unconfined(tracer)) return 0; if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) - return profile_ptrace_perm(tracer, tracee, request, sa); + return profile_ptrace_perm(cred, tracer, tracee, request, ad); /* profile uses the old style capability check for ptrace */ if (&tracer->label == tracee) return 0; - aad(sa)->label = &tracer->label; - aad(sa)->peer = tracee; - aad(sa)->request = 0; - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, - CAP_OPT_NONE); + ad->subj_label = &tracer->label; + ad->peer = tracee; + ad->request = 0; + ad->error = aa_capable(cred, &tracer->label, CAP_SYS_PTRACE, + CAP_OPT_NONE); - return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); + return aa_audit(AUDIT_APPARMOR_AUTO, tracer, ad, audit_ptrace_cb); } /** @@ -282,7 +284,8 @@ static int profile_tracer_perm(struct aa_profile *tracer, * * Returns: %0 else error code if permission denied or error */ -int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, +int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer, + const struct cred *tracee_cred, struct aa_label *tracee, u32 request) { struct aa_profile *profile; @@ -290,6 +293,49 @@ int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_PTRACE, OP_PTRACE); return xcheck_labels(tracer, tracee, profile, - profile_tracer_perm(profile, tracee, request, &sa), - profile_tracee_perm(profile, tracer, xrequest, &sa)); + profile_tracer_perm(tracer_cred, profile, tracee, + request, &sa), + profile_tracee_perm(tracee_cred, profile, tracer, + xrequest, &sa)); +} + +/* call back to audit ptrace fields */ +static void audit_ns_cb(struct audit_buffer *ab, void *va) +{ + struct apparmor_audit_data *ad = aad_of_va(va); + + if (ad->request & AA_USERNS_CREATE) + audit_log_format(ab, " requested=\"userns_create\""); + + if (ad->denied & AA_USERNS_CREATE) + audit_log_format(ab, " denied=\"userns_create\""); +} + +int aa_profile_ns_perm(struct aa_profile *profile, + struct apparmor_audit_data *ad, + u32 request) +{ + struct aa_perms perms = { }; + int error = 0; + + ad->subj_label = &profile->label; + ad->request = request; + + if (!profile_unconfined(profile)) { + struct aa_ruleset *rules = list_first_entry(&profile->rules, + typeof(*rules), + list); + aa_state_t state; + + state = RULE_MEDIATES(rules, ad->class); + if (!state) + /* TODO: add flag to complain about unmediated */ + return 0; + perms = *aa_lookup_perms(rules->policy, state); + aa_apply_modes_to_perms(profile, &perms); + error = aa_check_perms(profile, &perms, request, ad, + audit_ns_cb); + } + + return error; } diff --git a/security/landlock/Kconfig b/security/landlock/Kconfig index c1e862a38410..c4bf0d5eff39 100644 --- a/security/landlock/Kconfig +++ b/security/landlock/Kconfig @@ -3,6 +3,7 @@ config SECURITY_LANDLOCK bool "Landlock support" depends on SECURITY + select SECURITY_NETWORK select SECURITY_PATH help Landlock is a sandboxing mechanism that enables processes to restrict diff --git a/security/landlock/Makefile b/security/landlock/Makefile index 7bbd2f413b3e..c2e116f2a299 100644 --- a/security/landlock/Makefile +++ b/security/landlock/Makefile @@ -2,3 +2,5 @@ obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o landlock-y := setup.o syscalls.o object.o ruleset.o \ cred.o ptrace.o fs.o + +landlock-$(CONFIG_INET) += net.o diff --git a/security/landlock/fs.c b/security/landlock/fs.c index 1c0c198f6fdb..bc7c126deea2 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -150,16 +150,6 @@ retry: LANDLOCK_ACCESS_FS_TRUNCATE) /* clang-format on */ -/* - * All access rights that are denied by default whether they are handled or not - * by a ruleset/layer. This must be ORed with all ruleset->fs_access_masks[] - * entries when we need to get the absolute handled access masks. - */ -/* clang-format off */ -#define ACCESS_INITIALLY_DENIED ( \ - LANDLOCK_ACCESS_FS_REFER) -/* clang-format on */ - /* * @path: Should have been checked by get_path_from_fd(). */ @@ -168,7 +158,9 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, access_mask_t access_rights) { int err; - struct landlock_object *object; + struct landlock_id id = { + .type = LANDLOCK_KEY_INODE, + }; /* Files only get access rights that make sense. */ if (!d_is_dir(path->dentry) && @@ -178,20 +170,19 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, return -EINVAL; /* Transforms relative access rights to absolute ones. */ - access_rights |= - LANDLOCK_MASK_ACCESS_FS & - ~(ruleset->fs_access_masks[0] | ACCESS_INITIALLY_DENIED); - object = get_inode_object(d_backing_inode(path->dentry)); - if (IS_ERR(object)) - return PTR_ERR(object); + access_rights |= LANDLOCK_MASK_ACCESS_FS & + ~landlock_get_fs_access_mask(ruleset, 0); + id.key.object = get_inode_object(d_backing_inode(path->dentry)); + if (IS_ERR(id.key.object)) + return PTR_ERR(id.key.object); mutex_lock(&ruleset->lock); - err = landlock_insert_rule(ruleset, object, access_rights); + err = landlock_insert_rule(ruleset, id, access_rights); mutex_unlock(&ruleset->lock); /* * No need to check for an error because landlock_insert_rule() * increments the refcount for the new object if needed. */ - landlock_put_object(object); + landlock_put_object(id.key.object); return err; } @@ -208,6 +199,9 @@ find_rule(const struct landlock_ruleset *const domain, { const struct landlock_rule *rule; const struct inode *inode; + struct landlock_id id = { + .type = LANDLOCK_KEY_INODE, + }; /* Ignores nonexistent leafs. */ if (d_is_negative(dentry)) @@ -215,66 +209,12 @@ find_rule(const struct landlock_ruleset *const domain, inode = d_backing_inode(dentry); rcu_read_lock(); - rule = landlock_find_rule( - domain, rcu_dereference(landlock_inode(inode)->object)); + id.key.object = rcu_dereference(landlock_inode(inode)->object); + rule = landlock_find_rule(domain, id); rcu_read_unlock(); return rule; } -/* - * @layer_masks is read and may be updated according to the access request and - * the matching rule. - * - * Returns true if the request is allowed (i.e. relevant layer masks for the - * request are empty). - */ -static inline bool -unmask_layers(const struct landlock_rule *const rule, - const access_mask_t access_request, - layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS]) -{ - size_t layer_level; - - if (!access_request || !layer_masks) - return true; - if (!rule) - return false; - - /* - * An access is granted if, for each policy layer, at least one rule - * encountered on the pathwalk grants the requested access, - * regardless of its position in the layer stack. We must then check - * the remaining layers for each inode, from the first added layer to - * the last one. When there is multiple requested accesses, for each - * policy layer, the full set of requested accesses may not be granted - * by only one rule, but by the union (binary OR) of multiple rules. - * E.g. /a/b + /a => /a/b - */ - for (layer_level = 0; layer_level < rule->num_layers; layer_level++) { - const struct landlock_layer *const layer = - &rule->layers[layer_level]; - const layer_mask_t layer_bit = BIT_ULL(layer->level - 1); - const unsigned long access_req = access_request; - unsigned long access_bit; - bool is_empty; - - /* - * Records in @layer_masks which layer grants access to each - * requested access. - */ - is_empty = true; - for_each_set_bit(access_bit, &access_req, - ARRAY_SIZE(*layer_masks)) { - if (layer->access & BIT_ULL(access_bit)) - (*layer_masks)[access_bit] &= ~layer_bit; - is_empty = is_empty && !(*layer_masks)[access_bit]; - } - if (is_empty) - return true; - } - return false; -} - /* * Allows access to pseudo filesystems that will never be mountable (e.g. * sockfs, pipefs), but can still be reachable through @@ -287,64 +227,35 @@ static inline bool is_nouser_or_private(const struct dentry *dentry) unlikely(IS_PRIVATE(d_backing_inode(dentry)))); } -static inline access_mask_t -get_handled_accesses(const struct landlock_ruleset *const domain) +static access_mask_t +get_raw_handled_fs_accesses(const struct landlock_ruleset *const domain) { - access_mask_t access_dom = ACCESS_INITIALLY_DENIED; + access_mask_t access_dom = 0; size_t layer_level; for (layer_level = 0; layer_level < domain->num_layers; layer_level++) - access_dom |= domain->fs_access_masks[layer_level]; - return access_dom & LANDLOCK_MASK_ACCESS_FS; + access_dom |= + landlock_get_raw_fs_access_mask(domain, layer_level); + return access_dom; } -/** - * init_layer_masks - Initialize layer masks from an access request - * - * Populates @layer_masks such that for each access right in @access_request, - * the bits for all the layers are set where this access right is handled. - * - * @domain: The domain that defines the current restrictions. - * @access_request: The requested access rights to check. - * @layer_masks: The layer masks to populate. - * - * Returns: An access mask where each access right bit is set which is handled - * in any of the active layers in @domain. - */ -static inline access_mask_t -init_layer_masks(const struct landlock_ruleset *const domain, - const access_mask_t access_request, - layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS]) +static access_mask_t +get_handled_fs_accesses(const struct landlock_ruleset *const domain) { - access_mask_t handled_accesses = 0; - size_t layer_level; + /* Handles all initially denied by default access rights. */ + return get_raw_handled_fs_accesses(domain) | + LANDLOCK_ACCESS_FS_INITIALLY_DENIED; +} - memset(layer_masks, 0, sizeof(*layer_masks)); - /* An empty access request can happen because of O_WRONLY | O_RDWR. */ - if (!access_request) - return 0; +static const struct landlock_ruleset *get_current_fs_domain(void) +{ + const struct landlock_ruleset *const dom = + landlock_get_current_domain(); - /* Saves all handled accesses per layer. */ - for (layer_level = 0; layer_level < domain->num_layers; layer_level++) { - const unsigned long access_req = access_request; - unsigned long access_bit; + if (!dom || !get_raw_handled_fs_accesses(dom)) + return NULL; - for_each_set_bit(access_bit, &access_req, - ARRAY_SIZE(*layer_masks)) { - /* - * Artificially handles all initially denied by default - * access rights. - */ - if (BIT_ULL(access_bit) & - (domain->fs_access_masks[layer_level] | - ACCESS_INITIALLY_DENIED)) { - (*layer_masks)[access_bit] |= - BIT_ULL(layer_level); - handled_accesses |= BIT_ULL(access_bit); - } - } - } - return handled_accesses; + return dom; } /* @@ -519,7 +430,7 @@ static bool is_access_to_paths_allowed( * a superset of the meaningful requested accesses). */ access_masked_parent1 = access_masked_parent2 = - get_handled_accesses(domain); + get_handled_fs_accesses(domain); is_dom_check = true; } else { if (WARN_ON_ONCE(dentry_child1 || dentry_child2)) @@ -531,18 +442,22 @@ static bool is_access_to_paths_allowed( } if (unlikely(dentry_child1)) { - unmask_layers(find_rule(domain, dentry_child1), - init_layer_masks(domain, LANDLOCK_MASK_ACCESS_FS, - &_layer_masks_child1), - &_layer_masks_child1); + landlock_unmask_layers( + find_rule(domain, dentry_child1), + landlock_init_layer_masks( + domain, LANDLOCK_MASK_ACCESS_FS, + &_layer_masks_child1, LANDLOCK_KEY_INODE), + &_layer_masks_child1, ARRAY_SIZE(_layer_masks_child1)); layer_masks_child1 = &_layer_masks_child1; child1_is_directory = d_is_dir(dentry_child1); } if (unlikely(dentry_child2)) { - unmask_layers(find_rule(domain, dentry_child2), - init_layer_masks(domain, LANDLOCK_MASK_ACCESS_FS, - &_layer_masks_child2), - &_layer_masks_child2); + landlock_unmask_layers( + find_rule(domain, dentry_child2), + landlock_init_layer_masks( + domain, LANDLOCK_MASK_ACCESS_FS, + &_layer_masks_child2, LANDLOCK_KEY_INODE), + &_layer_masks_child2, ARRAY_SIZE(_layer_masks_child2)); layer_masks_child2 = &_layer_masks_child2; child2_is_directory = d_is_dir(dentry_child2); } @@ -594,15 +509,16 @@ static bool is_access_to_paths_allowed( } rule = find_rule(domain, walker_path.dentry); - allowed_parent1 = unmask_layers(rule, access_masked_parent1, - layer_masks_parent1); - allowed_parent2 = unmask_layers(rule, access_masked_parent2, - layer_masks_parent2); + allowed_parent1 = landlock_unmask_layers( + rule, access_masked_parent1, layer_masks_parent1, + ARRAY_SIZE(*layer_masks_parent1)); + allowed_parent2 = landlock_unmask_layers( + rule, access_masked_parent2, layer_masks_parent2, + ARRAY_SIZE(*layer_masks_parent2)); /* Stops when a rule from each layer grants access. */ if (allowed_parent1 && allowed_parent2) break; - jump_up: if (walker_path.dentry == walker_path.mnt->mnt_root) { if (follow_up(&walker_path)) { @@ -641,7 +557,8 @@ static inline int check_access_path(const struct landlock_ruleset *const domain, { layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; - access_request = init_layer_masks(domain, access_request, &layer_masks); + access_request = landlock_init_layer_masks( + domain, access_request, &layer_masks, LANDLOCK_KEY_INODE); if (is_access_to_paths_allowed(domain, path, access_request, &layer_masks, NULL, 0, NULL, NULL)) return 0; @@ -651,8 +568,7 @@ static inline int check_access_path(const struct landlock_ruleset *const domain, static inline int current_check_access_path(const struct path *const path, const access_mask_t access_request) { - const struct landlock_ruleset *const dom = - landlock_get_current_domain(); + const struct landlock_ruleset *const dom = get_current_fs_domain(); if (!dom) return 0; @@ -727,16 +643,18 @@ static bool collect_domain_accesses( if (is_nouser_or_private(dir)) return true; - access_dom = init_layer_masks(domain, LANDLOCK_MASK_ACCESS_FS, - layer_masks_dom); + access_dom = landlock_init_layer_masks(domain, LANDLOCK_MASK_ACCESS_FS, + layer_masks_dom, + LANDLOCK_KEY_INODE); dget(dir); while (true) { struct dentry *parent_dentry; /* Gets all layers allowing all domain accesses. */ - if (unmask_layers(find_rule(domain, dir), access_dom, - layer_masks_dom)) { + if (landlock_unmask_layers(find_rule(domain, dir), access_dom, + layer_masks_dom, + ARRAY_SIZE(*layer_masks_dom))) { /* * Stops when all handled accesses are allowed by at * least one rule in each layer. @@ -815,8 +733,7 @@ static int current_check_refer_path(struct dentry *const old_dentry, struct dentry *const new_dentry, const bool removable, const bool exchange) { - const struct landlock_ruleset *const dom = - landlock_get_current_domain(); + const struct landlock_ruleset *const dom = get_current_fs_domain(); bool allow_parent1, allow_parent2; access_mask_t access_request_parent1, access_request_parent2; struct path mnt_dir; @@ -850,9 +767,9 @@ static int current_check_refer_path(struct dentry *const old_dentry, * The LANDLOCK_ACCESS_FS_REFER access right is not required * for same-directory referer (i.e. no reparenting). */ - access_request_parent1 = init_layer_masks( + access_request_parent1 = landlock_init_layer_masks( dom, access_request_parent1 | access_request_parent2, - &layer_masks_parent1); + &layer_masks_parent1, LANDLOCK_KEY_INODE); if (is_access_to_paths_allowed( dom, new_dir, access_request_parent1, &layer_masks_parent1, NULL, 0, NULL, NULL)) @@ -1050,7 +967,7 @@ static int hook_sb_mount(const char *const dev_name, const struct path *const path, const char *const type, const unsigned long flags, void *const data) { - if (!landlock_get_current_domain()) + if (!get_current_fs_domain()) return 0; return -EPERM; } @@ -1058,7 +975,7 @@ static int hook_sb_mount(const char *const dev_name, static int hook_move_mount(const struct path *const from_path, const struct path *const to_path) { - if (!landlock_get_current_domain()) + if (!get_current_fs_domain()) return 0; return -EPERM; } @@ -1069,14 +986,14 @@ static int hook_move_mount(const struct path *const from_path, */ static int hook_sb_umount(struct vfsmount *const mnt, const int flags) { - if (!landlock_get_current_domain()) + if (!get_current_fs_domain()) return 0; return -EPERM; } static int hook_sb_remount(struct super_block *const sb, void *const mnt_opts) { - if (!landlock_get_current_domain()) + if (!get_current_fs_domain()) return 0; return -EPERM; } @@ -1092,7 +1009,7 @@ static int hook_sb_remount(struct super_block *const sb, void *const mnt_opts) static int hook_sb_pivotroot(const struct path *const old_path, const struct path *const new_path) { - if (!landlock_get_current_domain()) + if (!get_current_fs_domain()) return 0; return -EPERM; } @@ -1128,8 +1045,7 @@ static int hook_path_mknod(const struct path *const dir, struct dentry *const dentry, const umode_t mode, const unsigned int dev) { - const struct landlock_ruleset *const dom = - landlock_get_current_domain(); + const struct landlock_ruleset *const dom = get_current_fs_domain(); if (!dom) return 0; @@ -1208,8 +1124,7 @@ static int hook_file_open(struct file *const file) layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; access_mask_t open_access_request, full_access_request, allowed_access; const access_mask_t optional_access = LANDLOCK_ACCESS_FS_TRUNCATE; - const struct landlock_ruleset *const dom = - landlock_get_current_domain(); + const struct landlock_ruleset *const dom = get_current_fs_domain(); if (!dom) return 0; @@ -1229,7 +1144,8 @@ static int hook_file_open(struct file *const file) if (is_access_to_paths_allowed( dom, &file->f_path, - init_layer_masks(dom, full_access_request, &layer_masks), + landlock_init_layer_masks(dom, full_access_request, + &layer_masks, LANDLOCK_KEY_INODE), &layer_masks, NULL, 0, NULL, NULL)) { allowed_access = full_access_request; } else { diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 82288f0e9e5e..93c9c6f91556 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -21,6 +21,12 @@ #define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_TRUNCATE #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) +#define LANDLOCK_SHIFT_ACCESS_FS 0 + +#define LANDLOCK_LAST_ACCESS_NET LANDLOCK_ACCESS_NET_CONNECT_TCP +#define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1) +#define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET) +#define LANDLOCK_SHIFT_ACCESS_NET LANDLOCK_NUM_ACCESS_FS /* clang-format on */ diff --git a/security/landlock/net.c b/security/landlock/net.c new file mode 100644 index 000000000000..aaa92c2b1f08 --- /dev/null +++ b/security/landlock/net.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Landlock LSM - Network management and hooks + * + * Copyright © 2022-2023 Huawei Tech. Co., Ltd. + * Copyright © 2022-2023 Microsoft Corporation + */ + +#include +#include +#include +#include + +#include "common.h" +#include "cred.h" +#include "limits.h" +#include "net.h" +#include "ruleset.h" + +int landlock_append_net_rule(struct landlock_ruleset *const ruleset, + const u16 port, access_mask_t access_rights) +{ + int err; + const struct landlock_id id = { + .key.data = (__force uintptr_t)htons(port), + .type = LANDLOCK_KEY_NET_PORT, + }; + + BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); + + /* Transforms relative access rights to absolute ones. */ + access_rights |= LANDLOCK_MASK_ACCESS_NET & + ~landlock_get_net_access_mask(ruleset, 0); + + mutex_lock(&ruleset->lock); + err = landlock_insert_rule(ruleset, id, access_rights); + mutex_unlock(&ruleset->lock); + + return err; +} + +static access_mask_t +get_raw_handled_net_accesses(const struct landlock_ruleset *const domain) +{ + access_mask_t access_dom = 0; + size_t layer_level; + + for (layer_level = 0; layer_level < domain->num_layers; layer_level++) + access_dom |= landlock_get_net_access_mask(domain, layer_level); + return access_dom; +} + +static const struct landlock_ruleset *get_current_net_domain(void) +{ + const struct landlock_ruleset *const dom = + landlock_get_current_domain(); + + if (!dom || !get_raw_handled_net_accesses(dom)) + return NULL; + + return dom; +} + +static int current_check_access_socket(struct socket *const sock, + struct sockaddr *const address, + const int addrlen, + const access_mask_t access_request) +{ + __be16 port; + layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_NET] = {}; + const struct landlock_rule *rule; + access_mask_t handled_access; + struct landlock_id id = { + .type = LANDLOCK_KEY_NET_PORT, + }; + const struct landlock_ruleset *const dom = get_current_net_domain(); + + if (!dom) + return 0; + if (WARN_ON_ONCE(dom->num_layers < 1)) + return -EACCES; + + /* Checks if it's a (potential) TCP socket. */ + if (sock->type != SOCK_STREAM) + return 0; + + /* Checks for minimal header length to safely read sa_family. */ + if (addrlen < offsetofend(typeof(*address), sa_family)) + return -EINVAL; + + switch (address->sa_family) { + case AF_UNSPEC: + case AF_INET: + if (addrlen < sizeof(struct sockaddr_in)) + return -EINVAL; + port = ((struct sockaddr_in *)address)->sin_port; + break; + +#if IS_ENABLED(CONFIG_IPV6) + case AF_INET6: + if (addrlen < SIN6_LEN_RFC2133) + return -EINVAL; + port = ((struct sockaddr_in6 *)address)->sin6_port; + break; +#endif /* IS_ENABLED(CONFIG_IPV6) */ + + default: + return 0; + } + + /* Specific AF_UNSPEC handling. */ + if (address->sa_family == AF_UNSPEC) { + /* + * Connecting to an address with AF_UNSPEC dissolves the TCP + * association, which have the same effect as closing the + * connection while retaining the socket object (i.e., the file + * descriptor). As for dropping privileges, closing + * connections is always allowed. + * + * For a TCP access control system, this request is legitimate. + * Let the network stack handle potential inconsistencies and + * return -EINVAL if needed. + */ + if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) + return 0; + + /* + * For compatibility reason, accept AF_UNSPEC for bind + * accesses (mapped to AF_INET) only if the address is + * INADDR_ANY (cf. __inet_bind). Checking the address is + * required to not wrongfully return -EACCES instead of + * -EAFNOSUPPORT. + * + * We could return 0 and let the network stack handle these + * checks, but it is safer to return a proper error and test + * consistency thanks to kselftest. + */ + if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { + /* addrlen has already been checked for AF_UNSPEC. */ + const struct sockaddr_in *const sockaddr = + (struct sockaddr_in *)address; + + if (sock->sk->__sk_common.skc_family != AF_INET) + return -EINVAL; + + if (sockaddr->sin_addr.s_addr != htonl(INADDR_ANY)) + return -EAFNOSUPPORT; + } + } else { + /* + * Checks sa_family consistency to not wrongfully return + * -EACCES instead of -EINVAL. Valid sa_family changes are + * only (from AF_INET or AF_INET6) to AF_UNSPEC. + * + * We could return 0 and let the network stack handle this + * check, but it is safer to return a proper error and test + * consistency thanks to kselftest. + */ + if (address->sa_family != sock->sk->__sk_common.skc_family) + return -EINVAL; + } + + id.key.data = (__force uintptr_t)port; + BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); + + rule = landlock_find_rule(dom, id); + handled_access = landlock_init_layer_masks( + dom, access_request, &layer_masks, LANDLOCK_KEY_NET_PORT); + if (landlock_unmask_layers(rule, handled_access, &layer_masks, + ARRAY_SIZE(layer_masks))) + return 0; + + return -EACCES; +} + +static int hook_socket_bind(struct socket *const sock, + struct sockaddr *const address, const int addrlen) +{ + return current_check_access_socket(sock, address, addrlen, + LANDLOCK_ACCESS_NET_BIND_TCP); +} + +static int hook_socket_connect(struct socket *const sock, + struct sockaddr *const address, + const int addrlen) +{ + return current_check_access_socket(sock, address, addrlen, + LANDLOCK_ACCESS_NET_CONNECT_TCP); +} + +static struct security_hook_list landlock_hooks[] __ro_after_init = { + LSM_HOOK_INIT(socket_bind, hook_socket_bind), + LSM_HOOK_INIT(socket_connect, hook_socket_connect), +}; + +__init void landlock_add_net_hooks(void) +{ + security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), + LANDLOCK_NAME); +} diff --git a/security/landlock/net.h b/security/landlock/net.h new file mode 100644 index 000000000000..09960c237a13 --- /dev/null +++ b/security/landlock/net.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Landlock LSM - Network management and hooks + * + * Copyright © 2022-2023 Huawei Tech. Co., Ltd. + */ + +#ifndef _SECURITY_LANDLOCK_NET_H +#define _SECURITY_LANDLOCK_NET_H + +#include "common.h" +#include "ruleset.h" +#include "setup.h" + +#if IS_ENABLED(CONFIG_INET) +__init void landlock_add_net_hooks(void); + +int landlock_append_net_rule(struct landlock_ruleset *const ruleset, + const u16 port, access_mask_t access_rights); +#else /* IS_ENABLED(CONFIG_INET) */ +static inline void landlock_add_net_hooks(void) +{ +} + +static inline int +landlock_append_net_rule(struct landlock_ruleset *const ruleset, const u16 port, + access_mask_t access_rights) +{ + return -EAFNOSUPPORT; +} +#endif /* IS_ENABLED(CONFIG_INET) */ + +#endif /* _SECURITY_LANDLOCK_NET_H */ diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index 996484f98bfd..ffedc99f2b68 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -29,33 +29,43 @@ static struct landlock_ruleset *create_ruleset(const u32 num_layers) struct landlock_ruleset *new_ruleset; new_ruleset = - kzalloc(struct_size(new_ruleset, fs_access_masks, num_layers), + kzalloc(struct_size(new_ruleset, access_masks, num_layers), GFP_KERNEL_ACCOUNT); if (!new_ruleset) return ERR_PTR(-ENOMEM); refcount_set(&new_ruleset->usage, 1); mutex_init(&new_ruleset->lock); - new_ruleset->root = RB_ROOT; + new_ruleset->root_inode = RB_ROOT; + +#if IS_ENABLED(CONFIG_INET) + new_ruleset->root_net_port = RB_ROOT; +#endif /* IS_ENABLED(CONFIG_INET) */ + new_ruleset->num_layers = num_layers; /* * hierarchy = NULL * num_rules = 0 - * fs_access_masks[] = 0 + * access_masks[] = 0 */ return new_ruleset; } struct landlock_ruleset * -landlock_create_ruleset(const access_mask_t fs_access_mask) +landlock_create_ruleset(const access_mask_t fs_access_mask, + const access_mask_t net_access_mask) { struct landlock_ruleset *new_ruleset; /* Informs about useless ruleset. */ - if (!fs_access_mask) + if (!fs_access_mask && !net_access_mask) return ERR_PTR(-ENOMSG); new_ruleset = create_ruleset(1); - if (!IS_ERR(new_ruleset)) - new_ruleset->fs_access_masks[0] = fs_access_mask; + if (IS_ERR(new_ruleset)) + return new_ruleset; + if (fs_access_mask) + landlock_add_fs_access_mask(new_ruleset, fs_access_mask, 0); + if (net_access_mask) + landlock_add_net_access_mask(new_ruleset, net_access_mask, 0); return new_ruleset; } @@ -68,8 +78,25 @@ static void build_check_rule(void) BUILD_BUG_ON(rule.num_layers < LANDLOCK_MAX_NUM_LAYERS); } +static bool is_object_pointer(const enum landlock_key_type key_type) +{ + switch (key_type) { + case LANDLOCK_KEY_INODE: + return true; + +#if IS_ENABLED(CONFIG_INET) + case LANDLOCK_KEY_NET_PORT: + return false; +#endif /* IS_ENABLED(CONFIG_INET) */ + + default: + WARN_ON_ONCE(1); + return false; + } +} + static struct landlock_rule * -create_rule(struct landlock_object *const object, +create_rule(const struct landlock_id id, const struct landlock_layer (*const layers)[], const u32 num_layers, const struct landlock_layer *const new_layer) { @@ -90,8 +117,13 @@ create_rule(struct landlock_object *const object, if (!new_rule) return ERR_PTR(-ENOMEM); RB_CLEAR_NODE(&new_rule->node); - landlock_get_object(object); - new_rule->object = object; + if (is_object_pointer(id.type)) { + /* This should be catched by insert_rule(). */ + WARN_ON_ONCE(!id.key.object); + landlock_get_object(id.key.object); + } + + new_rule->key = id.key; new_rule->num_layers = new_num_layers; /* Copies the original layer stack. */ memcpy(new_rule->layers, layers, @@ -102,12 +134,32 @@ create_rule(struct landlock_object *const object, return new_rule; } -static void free_rule(struct landlock_rule *const rule) +static struct rb_root *get_root(struct landlock_ruleset *const ruleset, + const enum landlock_key_type key_type) +{ + switch (key_type) { + case LANDLOCK_KEY_INODE: + return &ruleset->root_inode; + +#if IS_ENABLED(CONFIG_INET) + case LANDLOCK_KEY_NET_PORT: + return &ruleset->root_net_port; +#endif /* IS_ENABLED(CONFIG_INET) */ + + default: + WARN_ON_ONCE(1); + return ERR_PTR(-EINVAL); + } +} + +static void free_rule(struct landlock_rule *const rule, + const enum landlock_key_type key_type) { might_sleep(); if (!rule) return; - landlock_put_object(rule->object); + if (is_object_pointer(key_type)) + landlock_put_object(rule->key.object); kfree(rule); } @@ -117,19 +169,21 @@ static void build_check_ruleset(void) .num_rules = ~0, .num_layers = ~0, }; - typeof(ruleset.fs_access_masks[0]) fs_access_mask = ~0; + typeof(ruleset.access_masks[0]) access_masks = ~0; BUILD_BUG_ON(ruleset.num_rules < LANDLOCK_MAX_NUM_RULES); BUILD_BUG_ON(ruleset.num_layers < LANDLOCK_MAX_NUM_LAYERS); - BUILD_BUG_ON(fs_access_mask < LANDLOCK_MASK_ACCESS_FS); + BUILD_BUG_ON(access_masks < + ((LANDLOCK_MASK_ACCESS_FS << LANDLOCK_SHIFT_ACCESS_FS) | + (LANDLOCK_MASK_ACCESS_NET << LANDLOCK_SHIFT_ACCESS_NET))); } /** * insert_rule - Create and insert a rule in a ruleset * * @ruleset: The ruleset to be updated. - * @object: The object to build the new rule with. The underlying kernel - * object must be held by the caller. + * @id: The ID to build the new rule with. The underlying kernel object, if + * any, must be held by the caller. * @layers: One or multiple layers to be copied into the new rule. * @num_layers: The number of @layers entries. * @@ -143,26 +197,35 @@ static void build_check_ruleset(void) * access rights. */ static int insert_rule(struct landlock_ruleset *const ruleset, - struct landlock_object *const object, + const struct landlock_id id, const struct landlock_layer (*const layers)[], - size_t num_layers) + const size_t num_layers) { struct rb_node **walker_node; struct rb_node *parent_node = NULL; struct landlock_rule *new_rule; + struct rb_root *root; might_sleep(); lockdep_assert_held(&ruleset->lock); - if (WARN_ON_ONCE(!object || !layers)) + if (WARN_ON_ONCE(!layers)) return -ENOENT; - walker_node = &(ruleset->root.rb_node); + + if (is_object_pointer(id.type) && WARN_ON_ONCE(!id.key.object)) + return -ENOENT; + + root = get_root(ruleset, id.type); + if (IS_ERR(root)) + return PTR_ERR(root); + + walker_node = &root->rb_node; while (*walker_node) { struct landlock_rule *const this = rb_entry(*walker_node, struct landlock_rule, node); - if (this->object != object) { + if (this->key.data != id.key.data) { parent_node = *walker_node; - if (this->object < object) + if (this->key.data < id.key.data) walker_node = &((*walker_node)->rb_right); else walker_node = &((*walker_node)->rb_left); @@ -194,24 +257,24 @@ static int insert_rule(struct landlock_ruleset *const ruleset, * Intersects access rights when it is a merge between a * ruleset and a domain. */ - new_rule = create_rule(object, &this->layers, this->num_layers, + new_rule = create_rule(id, &this->layers, this->num_layers, &(*layers)[0]); if (IS_ERR(new_rule)) return PTR_ERR(new_rule); - rb_replace_node(&this->node, &new_rule->node, &ruleset->root); - free_rule(this); + rb_replace_node(&this->node, &new_rule->node, root); + free_rule(this, id.type); return 0; } - /* There is no match for @object. */ + /* There is no match for @id. */ build_check_ruleset(); if (ruleset->num_rules >= LANDLOCK_MAX_NUM_RULES) return -E2BIG; - new_rule = create_rule(object, layers, num_layers, NULL); + new_rule = create_rule(id, layers, num_layers, NULL); if (IS_ERR(new_rule)) return PTR_ERR(new_rule); rb_link_node(&new_rule->node, parent_node, walker_node); - rb_insert_color(&new_rule->node, &ruleset->root); + rb_insert_color(&new_rule->node, root); ruleset->num_rules++; return 0; } @@ -229,7 +292,7 @@ static void build_check_layer(void) /* @ruleset must be locked by the caller. */ int landlock_insert_rule(struct landlock_ruleset *const ruleset, - struct landlock_object *const object, + const struct landlock_id id, const access_mask_t access) { struct landlock_layer layers[] = { { @@ -239,7 +302,7 @@ int landlock_insert_rule(struct landlock_ruleset *const ruleset, } }; build_check_layer(); - return insert_rule(ruleset, object, &layers, ARRAY_SIZE(layers)); + return insert_rule(ruleset, id, &layers, ARRAY_SIZE(layers)); } static inline void get_hierarchy(struct landlock_hierarchy *const hierarchy) @@ -258,10 +321,51 @@ static void put_hierarchy(struct landlock_hierarchy *hierarchy) } } +static int merge_tree(struct landlock_ruleset *const dst, + struct landlock_ruleset *const src, + const enum landlock_key_type key_type) +{ + struct landlock_rule *walker_rule, *next_rule; + struct rb_root *src_root; + int err = 0; + + might_sleep(); + lockdep_assert_held(&dst->lock); + lockdep_assert_held(&src->lock); + + src_root = get_root(src, key_type); + if (IS_ERR(src_root)) + return PTR_ERR(src_root); + + /* Merges the @src tree. */ + rbtree_postorder_for_each_entry_safe(walker_rule, next_rule, src_root, + node) { + struct landlock_layer layers[] = { { + .level = dst->num_layers, + } }; + const struct landlock_id id = { + .key = walker_rule->key, + .type = key_type, + }; + + if (WARN_ON_ONCE(walker_rule->num_layers != 1)) + return -EINVAL; + + if (WARN_ON_ONCE(walker_rule->layers[0].level != 0)) + return -EINVAL; + + layers[0].access = walker_rule->layers[0].access; + + err = insert_rule(dst, id, &layers, ARRAY_SIZE(layers)); + if (err) + return err; + } + return err; +} + static int merge_ruleset(struct landlock_ruleset *const dst, struct landlock_ruleset *const src) { - struct landlock_rule *walker_rule, *next_rule; int err = 0; might_sleep(); @@ -281,29 +385,19 @@ static int merge_ruleset(struct landlock_ruleset *const dst, err = -EINVAL; goto out_unlock; } - dst->fs_access_masks[dst->num_layers - 1] = src->fs_access_masks[0]; + dst->access_masks[dst->num_layers - 1] = src->access_masks[0]; - /* Merges the @src tree. */ - rbtree_postorder_for_each_entry_safe(walker_rule, next_rule, &src->root, - node) { - struct landlock_layer layers[] = { { - .level = dst->num_layers, - } }; + /* Merges the @src inode tree. */ + err = merge_tree(dst, src, LANDLOCK_KEY_INODE); + if (err) + goto out_unlock; - if (WARN_ON_ONCE(walker_rule->num_layers != 1)) { - err = -EINVAL; - goto out_unlock; - } - if (WARN_ON_ONCE(walker_rule->layers[0].level != 0)) { - err = -EINVAL; - goto out_unlock; - } - layers[0].access = walker_rule->layers[0].access; - err = insert_rule(dst, walker_rule->object, &layers, - ARRAY_SIZE(layers)); - if (err) - goto out_unlock; - } +#if IS_ENABLED(CONFIG_INET) + /* Merges the @src network port tree. */ + err = merge_tree(dst, src, LANDLOCK_KEY_NET_PORT); + if (err) + goto out_unlock; +#endif /* IS_ENABLED(CONFIG_INET) */ out_unlock: mutex_unlock(&src->lock); @@ -311,10 +405,41 @@ out_unlock: return err; } +static int inherit_tree(struct landlock_ruleset *const parent, + struct landlock_ruleset *const child, + const enum landlock_key_type key_type) +{ + struct landlock_rule *walker_rule, *next_rule; + struct rb_root *parent_root; + int err = 0; + + might_sleep(); + lockdep_assert_held(&parent->lock); + lockdep_assert_held(&child->lock); + + parent_root = get_root(parent, key_type); + if (IS_ERR(parent_root)) + return PTR_ERR(parent_root); + + /* Copies the @parent inode or network tree. */ + rbtree_postorder_for_each_entry_safe(walker_rule, next_rule, + parent_root, node) { + const struct landlock_id id = { + .key = walker_rule->key, + .type = key_type, + }; + + err = insert_rule(child, id, &walker_rule->layers, + walker_rule->num_layers); + if (err) + return err; + } + return err; +} + static int inherit_ruleset(struct landlock_ruleset *const parent, struct landlock_ruleset *const child) { - struct landlock_rule *walker_rule, *next_rule; int err = 0; might_sleep(); @@ -325,23 +450,25 @@ static int inherit_ruleset(struct landlock_ruleset *const parent, mutex_lock(&child->lock); mutex_lock_nested(&parent->lock, SINGLE_DEPTH_NESTING); - /* Copies the @parent tree. */ - rbtree_postorder_for_each_entry_safe(walker_rule, next_rule, - &parent->root, node) { - err = insert_rule(child, walker_rule->object, - &walker_rule->layers, - walker_rule->num_layers); - if (err) - goto out_unlock; - } + /* Copies the @parent inode tree. */ + err = inherit_tree(parent, child, LANDLOCK_KEY_INODE); + if (err) + goto out_unlock; + +#if IS_ENABLED(CONFIG_INET) + /* Copies the @parent network port tree. */ + err = inherit_tree(parent, child, LANDLOCK_KEY_NET_PORT); + if (err) + goto out_unlock; +#endif /* IS_ENABLED(CONFIG_INET) */ if (WARN_ON_ONCE(child->num_layers <= parent->num_layers)) { err = -EINVAL; goto out_unlock; } /* Copies the parent layer stack and leaves a space for the new layer. */ - memcpy(child->fs_access_masks, parent->fs_access_masks, - flex_array_size(parent, fs_access_masks, parent->num_layers)); + memcpy(child->access_masks, parent->access_masks, + flex_array_size(parent, access_masks, parent->num_layers)); if (WARN_ON_ONCE(!parent->hierarchy)) { err = -EINVAL; @@ -361,8 +488,16 @@ static void free_ruleset(struct landlock_ruleset *const ruleset) struct landlock_rule *freeme, *next; might_sleep(); - rbtree_postorder_for_each_entry_safe(freeme, next, &ruleset->root, node) - free_rule(freeme); + rbtree_postorder_for_each_entry_safe(freeme, next, &ruleset->root_inode, + node) + free_rule(freeme, LANDLOCK_KEY_INODE); + +#if IS_ENABLED(CONFIG_INET) + rbtree_postorder_for_each_entry_safe(freeme, next, + &ruleset->root_net_port, node) + free_rule(freeme, LANDLOCK_KEY_NET_PORT); +#endif /* IS_ENABLED(CONFIG_INET) */ + put_hierarchy(ruleset->hierarchy); kfree(ruleset); } @@ -453,23 +588,151 @@ out_put_dom: */ const struct landlock_rule * landlock_find_rule(const struct landlock_ruleset *const ruleset, - const struct landlock_object *const object) + const struct landlock_id id) { + const struct rb_root *root; const struct rb_node *node; - if (!object) + root = get_root((struct landlock_ruleset *)ruleset, id.type); + if (IS_ERR(root)) return NULL; - node = ruleset->root.rb_node; + node = root->rb_node; + while (node) { struct landlock_rule *this = rb_entry(node, struct landlock_rule, node); - if (this->object == object) + if (this->key.data == id.key.data) return this; - if (this->object < object) + if (this->key.data < id.key.data) node = node->rb_right; else node = node->rb_left; } return NULL; } + +/* + * @layer_masks is read and may be updated according to the access request and + * the matching rule. + * @masks_array_size must be equal to ARRAY_SIZE(*layer_masks). + * + * Returns true if the request is allowed (i.e. relevant layer masks for the + * request are empty). + */ +bool landlock_unmask_layers(const struct landlock_rule *const rule, + const access_mask_t access_request, + layer_mask_t (*const layer_masks)[], + const size_t masks_array_size) +{ + size_t layer_level; + + if (!access_request || !layer_masks) + return true; + if (!rule) + return false; + + /* + * An access is granted if, for each policy layer, at least one rule + * encountered on the pathwalk grants the requested access, + * regardless of its position in the layer stack. We must then check + * the remaining layers for each inode, from the first added layer to + * the last one. When there is multiple requested accesses, for each + * policy layer, the full set of requested accesses may not be granted + * by only one rule, but by the union (binary OR) of multiple rules. + * E.g. /a/b + /a => /a/b + */ + for (layer_level = 0; layer_level < rule->num_layers; layer_level++) { + const struct landlock_layer *const layer = + &rule->layers[layer_level]; + const layer_mask_t layer_bit = BIT_ULL(layer->level - 1); + const unsigned long access_req = access_request; + unsigned long access_bit; + bool is_empty; + + /* + * Records in @layer_masks which layer grants access to each + * requested access. + */ + is_empty = true; + for_each_set_bit(access_bit, &access_req, masks_array_size) { + if (layer->access & BIT_ULL(access_bit)) + (*layer_masks)[access_bit] &= ~layer_bit; + is_empty = is_empty && !(*layer_masks)[access_bit]; + } + if (is_empty) + return true; + } + return false; +} + +typedef access_mask_t +get_access_mask_t(const struct landlock_ruleset *const ruleset, + const u16 layer_level); + +/** + * landlock_init_layer_masks - Initialize layer masks from an access request + * + * Populates @layer_masks such that for each access right in @access_request, + * the bits for all the layers are set where this access right is handled. + * + * @domain: The domain that defines the current restrictions. + * @access_request: The requested access rights to check. + * @layer_masks: It must contain %LANDLOCK_NUM_ACCESS_FS or + * %LANDLOCK_NUM_ACCESS_NET elements according to @key_type. + * @key_type: The key type to switch between access masks of different types. + * + * Returns: An access mask where each access right bit is set which is handled + * in any of the active layers in @domain. + */ +access_mask_t +landlock_init_layer_masks(const struct landlock_ruleset *const domain, + const access_mask_t access_request, + layer_mask_t (*const layer_masks)[], + const enum landlock_key_type key_type) +{ + access_mask_t handled_accesses = 0; + size_t layer_level, num_access; + get_access_mask_t *get_access_mask; + + switch (key_type) { + case LANDLOCK_KEY_INODE: + get_access_mask = landlock_get_fs_access_mask; + num_access = LANDLOCK_NUM_ACCESS_FS; + break; + +#if IS_ENABLED(CONFIG_INET) + case LANDLOCK_KEY_NET_PORT: + get_access_mask = landlock_get_net_access_mask; + num_access = LANDLOCK_NUM_ACCESS_NET; + break; +#endif /* IS_ENABLED(CONFIG_INET) */ + + default: + WARN_ON_ONCE(1); + return 0; + } + + memset(layer_masks, 0, + array_size(sizeof((*layer_masks)[0]), num_access)); + + /* An empty access request can happen because of O_WRONLY | O_RDWR. */ + if (!access_request) + return 0; + + /* Saves all handled accesses per layer. */ + for (layer_level = 0; layer_level < domain->num_layers; layer_level++) { + const unsigned long access_req = access_request; + unsigned long access_bit; + + for_each_set_bit(access_bit, &access_req, num_access) { + if (BIT_ULL(access_bit) & + get_access_mask(domain, layer_level)) { + (*layer_masks)[access_bit] |= + BIT_ULL(layer_level); + handled_accesses |= BIT_ULL(access_bit); + } + } + } + return handled_accesses; +} diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h index 55b1df8f66a8..c7f1526784fd 100644 --- a/security/landlock/ruleset.h +++ b/security/landlock/ruleset.h @@ -15,16 +15,35 @@ #include #include #include +#include #include "limits.h" #include "object.h" +/* + * All access rights that are denied by default whether they are handled or not + * by a ruleset/layer. This must be ORed with all ruleset->access_masks[] + * entries when we need to get the absolute handled access masks. + */ +/* clang-format off */ +#define LANDLOCK_ACCESS_FS_INITIALLY_DENIED ( \ + LANDLOCK_ACCESS_FS_REFER) +/* clang-format on */ + typedef u16 access_mask_t; /* Makes sure all filesystem access rights can be stored. */ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS); +/* Makes sure all network access rights can be stored. */ +static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_NET); /* Makes sure for_each_set_bit() and for_each_clear_bit() calls are OK. */ static_assert(sizeof(unsigned long) >= sizeof(access_mask_t)); +/* Ruleset access masks. */ +typedef u32 access_masks_t; +/* Makes sure all ruleset access rights can be stored. */ +static_assert(BITS_PER_TYPE(access_masks_t) >= + LANDLOCK_NUM_ACCESS_FS + LANDLOCK_NUM_ACCESS_NET); + typedef u16 layer_mask_t; /* Makes sure all layers can be checked. */ static_assert(BITS_PER_TYPE(layer_mask_t) >= LANDLOCK_MAX_NUM_LAYERS); @@ -44,6 +63,52 @@ struct landlock_layer { access_mask_t access; }; +/** + * union landlock_key - Key of a ruleset's red-black tree + */ +union landlock_key { + /** + * @object: Pointer to identify a kernel object (e.g. an inode). + */ + struct landlock_object *object; + /** + * @data: Raw data to identify an arbitrary 32-bit value + * (e.g. a TCP port). + */ + uintptr_t data; +}; + +/** + * enum landlock_key_type - Type of &union landlock_key + */ +enum landlock_key_type { + /** + * @LANDLOCK_KEY_INODE: Type of &landlock_ruleset.root_inode's node + * keys. + */ + LANDLOCK_KEY_INODE = 1, + /** + * @LANDLOCK_KEY_NET_PORT: Type of &landlock_ruleset.root_net_port's + * node keys. + */ + LANDLOCK_KEY_NET_PORT, +}; + +/** + * struct landlock_id - Unique rule identifier for a ruleset + */ +struct landlock_id { + /** + * @key: Identifies either a kernel object (e.g. an inode) or + * a raw value (e.g. a TCP port). + */ + union landlock_key key; + /** + * @type: Type of a landlock_ruleset's root tree. + */ + const enum landlock_key_type type; +}; + /** * struct landlock_rule - Access rights tied to an object */ @@ -53,12 +118,13 @@ struct landlock_rule { */ struct rb_node node; /** - * @object: Pointer to identify a kernel object (e.g. an inode). This - * is used as a key for this ruleset element. This pointer is set once - * and never modified. It always points to an allocated object because - * each rule increments the refcount of its object. + * @key: A union to identify either a kernel object (e.g. an inode) or + * a raw data value (e.g. a network socket port). This is used as a key + * for this ruleset element. The pointer is set once and never + * modified. It always points to an allocated object because each rule + * increments the refcount of its object. */ - struct landlock_object *object; + union landlock_key key; /** * @num_layers: Number of entries in @layers. */ @@ -94,11 +160,23 @@ struct landlock_hierarchy { */ struct landlock_ruleset { /** - * @root: Root of a red-black tree containing &struct landlock_rule - * nodes. Once a ruleset is tied to a process (i.e. as a domain), this - * tree is immutable until @usage reaches zero. + * @root_inode: Root of a red-black tree containing &struct + * landlock_rule nodes with inode object. Once a ruleset is tied to a + * process (i.e. as a domain), this tree is immutable until @usage + * reaches zero. */ - struct rb_root root; + struct rb_root root_inode; + +#if IS_ENABLED(CONFIG_INET) + /** + * @root_net_port: Root of a red-black tree containing &struct + * landlock_rule nodes with network port. Once a ruleset is tied to a + * process (i.e. as a domain), this tree is immutable until @usage + * reaches zero. + */ + struct rb_root root_net_port; +#endif /* IS_ENABLED(CONFIG_INET) */ + /** * @hierarchy: Enables hierarchy identification even when a parent * domain vanishes. This is needed for the ptrace protection. @@ -110,7 +188,7 @@ struct landlock_ruleset { * section. This is only used by * landlock_put_ruleset_deferred() when @usage reaches zero. * The fields @lock, @usage, @num_rules, @num_layers and - * @fs_access_masks are then unused. + * @access_masks are then unused. */ struct work_struct work_free; struct { @@ -137,30 +215,31 @@ struct landlock_ruleset { */ u32 num_layers; /** - * @fs_access_masks: Contains the subset of filesystem - * actions that are restricted by a ruleset. A domain - * saves all layers of merged rulesets in a stack - * (FAM), starting from the first layer to the last - * one. These layers are used when merging rulesets, - * for user space backward compatibility (i.e. - * future-proof), and to properly handle merged + * @access_masks: Contains the subset of filesystem and + * network actions that are restricted by a ruleset. + * A domain saves all layers of merged rulesets in a + * stack (FAM), starting from the first layer to the + * last one. These layers are used when merging + * rulesets, for user space backward compatibility + * (i.e. future-proof), and to properly handle merged * rulesets without overlapping access rights. These * layers are set once and never changed for the * lifetime of the ruleset. */ - access_mask_t fs_access_masks[]; + access_masks_t access_masks[]; }; }; }; struct landlock_ruleset * -landlock_create_ruleset(const access_mask_t fs_access_mask); +landlock_create_ruleset(const access_mask_t access_mask_fs, + const access_mask_t access_mask_net); void landlock_put_ruleset(struct landlock_ruleset *const ruleset); void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset); int landlock_insert_rule(struct landlock_ruleset *const ruleset, - struct landlock_object *const object, + const struct landlock_id id, const access_mask_t access); struct landlock_ruleset * @@ -169,7 +248,7 @@ landlock_merge_ruleset(struct landlock_ruleset *const parent, const struct landlock_rule * landlock_find_rule(const struct landlock_ruleset *const ruleset, - const struct landlock_object *const object); + const struct landlock_id id); static inline void landlock_get_ruleset(struct landlock_ruleset *const ruleset) { @@ -177,4 +256,68 @@ static inline void landlock_get_ruleset(struct landlock_ruleset *const ruleset) refcount_inc(&ruleset->usage); } +static inline void +landlock_add_fs_access_mask(struct landlock_ruleset *const ruleset, + const access_mask_t fs_access_mask, + const u16 layer_level) +{ + access_mask_t fs_mask = fs_access_mask & LANDLOCK_MASK_ACCESS_FS; + + /* Should already be checked in sys_landlock_create_ruleset(). */ + WARN_ON_ONCE(fs_access_mask != fs_mask); + ruleset->access_masks[layer_level] |= + (fs_mask << LANDLOCK_SHIFT_ACCESS_FS); +} + +static inline void +landlock_add_net_access_mask(struct landlock_ruleset *const ruleset, + const access_mask_t net_access_mask, + const u16 layer_level) +{ + access_mask_t net_mask = net_access_mask & LANDLOCK_MASK_ACCESS_NET; + + /* Should already be checked in sys_landlock_create_ruleset(). */ + WARN_ON_ONCE(net_access_mask != net_mask); + ruleset->access_masks[layer_level] |= + (net_mask << LANDLOCK_SHIFT_ACCESS_NET); +} + +static inline access_mask_t +landlock_get_raw_fs_access_mask(const struct landlock_ruleset *const ruleset, + const u16 layer_level) +{ + return (ruleset->access_masks[layer_level] >> + LANDLOCK_SHIFT_ACCESS_FS) & + LANDLOCK_MASK_ACCESS_FS; +} + +static inline access_mask_t +landlock_get_fs_access_mask(const struct landlock_ruleset *const ruleset, + const u16 layer_level) +{ + /* Handles all initially denied by default access rights. */ + return landlock_get_raw_fs_access_mask(ruleset, layer_level) | + LANDLOCK_ACCESS_FS_INITIALLY_DENIED; +} + +static inline access_mask_t +landlock_get_net_access_mask(const struct landlock_ruleset *const ruleset, + const u16 layer_level) +{ + return (ruleset->access_masks[layer_level] >> + LANDLOCK_SHIFT_ACCESS_NET) & + LANDLOCK_MASK_ACCESS_NET; +} + +bool landlock_unmask_layers(const struct landlock_rule *const rule, + const access_mask_t access_request, + layer_mask_t (*const layer_masks)[], + const size_t masks_array_size); + +access_mask_t +landlock_init_layer_masks(const struct landlock_ruleset *const domain, + const access_mask_t access_request, + layer_mask_t (*const layer_masks)[], + const enum landlock_key_type key_type); + #endif /* _SECURITY_LANDLOCK_RULESET_H */ diff --git a/security/landlock/setup.c b/security/landlock/setup.c index 0f6113528fa4..3e11d303542f 100644 --- a/security/landlock/setup.c +++ b/security/landlock/setup.c @@ -12,6 +12,7 @@ #include "common.h" #include "cred.h" #include "fs.h" +#include "net.h" #include "ptrace.h" #include "setup.h" @@ -29,6 +30,7 @@ static int __init landlock_init(void) landlock_add_cred_hooks(); landlock_add_ptrace_hooks(); landlock_add_fs_hooks(); + landlock_add_net_hooks(); landlock_initialized = true; pr_info("Up and running.\n"); return 0; diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 245cc650a4dc..898358f57fa0 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -29,6 +29,7 @@ #include "cred.h" #include "fs.h" #include "limits.h" +#include "net.h" #include "ruleset.h" #include "setup.h" @@ -74,7 +75,8 @@ static void build_check_abi(void) { struct landlock_ruleset_attr ruleset_attr; struct landlock_path_beneath_attr path_beneath_attr; - size_t ruleset_size, path_beneath_size; + struct landlock_net_port_attr net_port_attr; + size_t ruleset_size, path_beneath_size, net_port_size; /* * For each user space ABI structures, first checks that there is no @@ -82,13 +84,19 @@ static void build_check_abi(void) * struct size. */ ruleset_size = sizeof(ruleset_attr.handled_access_fs); + ruleset_size += sizeof(ruleset_attr.handled_access_net); BUILD_BUG_ON(sizeof(ruleset_attr) != ruleset_size); - BUILD_BUG_ON(sizeof(ruleset_attr) != 8); + BUILD_BUG_ON(sizeof(ruleset_attr) != 16); path_beneath_size = sizeof(path_beneath_attr.allowed_access); path_beneath_size += sizeof(path_beneath_attr.parent_fd); BUILD_BUG_ON(sizeof(path_beneath_attr) != path_beneath_size); BUILD_BUG_ON(sizeof(path_beneath_attr) != 12); + + net_port_size = sizeof(net_port_attr.allowed_access); + net_port_size += sizeof(net_port_attr.port); + BUILD_BUG_ON(sizeof(net_port_attr) != net_port_size); + BUILD_BUG_ON(sizeof(net_port_attr) != 16); } /* Ruleset handling */ @@ -129,7 +137,7 @@ static const struct file_operations ruleset_fops = { .write = fop_dummy_write, }; -#define LANDLOCK_ABI_VERSION 3 +#define LANDLOCK_ABI_VERSION 4 /** * sys_landlock_create_ruleset - Create a new ruleset @@ -188,8 +196,14 @@ SYSCALL_DEFINE3(landlock_create_ruleset, LANDLOCK_MASK_ACCESS_FS) return -EINVAL; + /* Checks network content (and 32-bits cast). */ + if ((ruleset_attr.handled_access_net | LANDLOCK_MASK_ACCESS_NET) != + LANDLOCK_MASK_ACCESS_NET) + return -EINVAL; + /* Checks arguments and transforms to kernel struct. */ - ruleset = landlock_create_ruleset(ruleset_attr.handled_access_fs); + ruleset = landlock_create_ruleset(ruleset_attr.handled_access_fs, + ruleset_attr.handled_access_net); if (IS_ERR(ruleset)) return PTR_ERR(ruleset); @@ -274,13 +288,84 @@ out_fdput: return err; } +static int add_rule_path_beneath(struct landlock_ruleset *const ruleset, + const void __user *const rule_attr) +{ + struct landlock_path_beneath_attr path_beneath_attr; + struct path path; + int res, err; + access_mask_t mask; + + /* Copies raw user space buffer. */ + res = copy_from_user(&path_beneath_attr, rule_attr, + sizeof(path_beneath_attr)); + if (res) + return -EFAULT; + + /* + * Informs about useless rule: empty allowed_access (i.e. deny rules) + * are ignored in path walks. + */ + if (!path_beneath_attr.allowed_access) + return -ENOMSG; + + /* Checks that allowed_access matches the @ruleset constraints. */ + mask = landlock_get_raw_fs_access_mask(ruleset, 0); + if ((path_beneath_attr.allowed_access | mask) != mask) + return -EINVAL; + + /* Gets and checks the new rule. */ + err = get_path_from_fd(path_beneath_attr.parent_fd, &path); + if (err) + return err; + + /* Imports the new rule. */ + err = landlock_append_fs_rule(ruleset, &path, + path_beneath_attr.allowed_access); + path_put(&path); + return err; +} + +static int add_rule_net_port(struct landlock_ruleset *ruleset, + const void __user *const rule_attr) +{ + struct landlock_net_port_attr net_port_attr; + int res; + access_mask_t mask; + + /* Copies raw user space buffer. */ + res = copy_from_user(&net_port_attr, rule_attr, sizeof(net_port_attr)); + if (res) + return -EFAULT; + + /* + * Informs about useless rule: empty allowed_access (i.e. deny rules) + * are ignored by network actions. + */ + if (!net_port_attr.allowed_access) + return -ENOMSG; + + /* Checks that allowed_access matches the @ruleset constraints. */ + mask = landlock_get_net_access_mask(ruleset, 0); + if ((net_port_attr.allowed_access | mask) != mask) + return -EINVAL; + + /* Denies inserting a rule with port greater than 65535. */ + if (net_port_attr.port > U16_MAX) + return -EINVAL; + + /* Imports the new rule. */ + return landlock_append_net_rule(ruleset, net_port_attr.port, + net_port_attr.allowed_access); +} + /** * sys_landlock_add_rule - Add a new rule to a ruleset * * @ruleset_fd: File descriptor tied to the ruleset that should be extended * with the new rule. - * @rule_type: Identify the structure type pointed to by @rule_attr (only - * %LANDLOCK_RULE_PATH_BENEATH for now). + * @rule_type: Identify the structure type pointed to by @rule_attr: + * %LANDLOCK_RULE_PATH_BENEATH or %LANDLOCK_RULE_NET_PORT. * @rule_attr: Pointer to a rule (only of type &struct * landlock_path_beneath_attr for now). * @flags: Must be 0. @@ -291,9 +376,13 @@ out_fdput: * Possible returned errors are: * * - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time; + * - %EAFNOSUPPORT: @rule_type is %LANDLOCK_RULE_NET_PORT but TCP/IP is not + * supported by the running kernel; * - %EINVAL: @flags is not 0, or inconsistent access in the rule (i.e. - * &landlock_path_beneath_attr.allowed_access is not a subset of the - * ruleset handled accesses); + * &landlock_path_beneath_attr.allowed_access or + * &landlock_net_port_attr.allowed_access is not a subset of the + * ruleset handled accesses), or &landlock_net_port_attr.port is + * greater than 65535; * - %ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access); * - %EBADF: @ruleset_fd is not a file descriptor for the current thread, or a * member of @rule_attr is not a file descriptor as expected; @@ -306,10 +395,8 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd, const enum landlock_rule_type, rule_type, const void __user *const, rule_attr, const __u32, flags) { - struct landlock_path_beneath_attr path_beneath_attr; - struct path path; struct landlock_ruleset *ruleset; - int res, err; + int err; if (!landlock_initialized) return -EOPNOTSUPP; @@ -323,48 +410,17 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd, if (IS_ERR(ruleset)) return PTR_ERR(ruleset); - if (rule_type != LANDLOCK_RULE_PATH_BENEATH) { + switch (rule_type) { + case LANDLOCK_RULE_PATH_BENEATH: + err = add_rule_path_beneath(ruleset, rule_attr); + break; + case LANDLOCK_RULE_NET_PORT: + err = add_rule_net_port(ruleset, rule_attr); + break; + default: err = -EINVAL; - goto out_put_ruleset; + break; } - - /* Copies raw user space buffer, only one type for now. */ - res = copy_from_user(&path_beneath_attr, rule_attr, - sizeof(path_beneath_attr)); - if (res) { - err = -EFAULT; - goto out_put_ruleset; - } - - /* - * Informs about useless rule: empty allowed_access (i.e. deny rules) - * are ignored in path walks. - */ - if (!path_beneath_attr.allowed_access) { - err = -ENOMSG; - goto out_put_ruleset; - } - /* - * Checks that allowed_access matches the @ruleset constraints - * (ruleset->fs_access_masks[0] is automatically upgraded to 64-bits). - */ - if ((path_beneath_attr.allowed_access | ruleset->fs_access_masks[0]) != - ruleset->fs_access_masks[0]) { - err = -EINVAL; - goto out_put_ruleset; - } - - /* Gets and checks the new rule. */ - err = get_path_from_fd(path_beneath_attr.parent_fd, &path); - if (err) - goto out_put_ruleset; - - /* Imports the new rule. */ - err = landlock_append_fs_rule(ruleset, &path, - path_beneath_attr.allowed_access); - path_put(&path); - -out_put_ruleset: landlock_put_ruleset(ruleset); return err; } diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build index fac42486a8cf..5fb3fb3d97e0 100644 --- a/tools/build/Makefile.build +++ b/tools/build/Makefile.build @@ -20,7 +20,15 @@ else Q=@ endif -ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) +# If the user is running make -s (silent mode), suppress echoing of commands +# make-4.0 (and later) keep single letter options in the 1st word of MAKEFLAGS. +ifeq ($(filter 3.%,$(MAKE_VERSION)),) +short-opts := $(firstword -$(MAKEFLAGS)) +else +short-opts := $(filter-out --%,$(MAKEFLAGS)) +endif + +ifneq ($(findstring s,$(short-opts)),) quiet=silent_ endif diff --git a/tools/include/asm-generic/unaligned.h b/tools/include/asm-generic/unaligned.h index 47387c607035..156743d399ae 100644 --- a/tools/include/asm-generic/unaligned.h +++ b/tools/include/asm-generic/unaligned.h @@ -1,10 +1,13 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copied from the kernel sources to tools/perf/: - */ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ASM_GENERIC_UNALIGNED_H +#define __ASM_GENERIC_UNALIGNED_H -#ifndef __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H -#define __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H +/* + * This is the most generic implementation of unaligned accesses + * and should work almost anywhere. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpacked" #define __get_unaligned_t(type, ptr) ({ \ const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ @@ -19,5 +22,135 @@ #define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) #define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr)) -#endif /* __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H */ +static inline u16 get_unaligned_le16(const void *p) +{ + return le16_to_cpu(__get_unaligned_t(__le16, p)); +} +static inline u32 get_unaligned_le32(const void *p) +{ + return le32_to_cpu(__get_unaligned_t(__le32, p)); +} + +static inline u64 get_unaligned_le64(const void *p) +{ + return le64_to_cpu(__get_unaligned_t(__le64, p)); +} + +static inline void put_unaligned_le16(u16 val, void *p) +{ + __put_unaligned_t(__le16, cpu_to_le16(val), p); +} + +static inline void put_unaligned_le32(u32 val, void *p) +{ + __put_unaligned_t(__le32, cpu_to_le32(val), p); +} + +static inline void put_unaligned_le64(u64 val, void *p) +{ + __put_unaligned_t(__le64, cpu_to_le64(val), p); +} + +static inline u16 get_unaligned_be16(const void *p) +{ + return be16_to_cpu(__get_unaligned_t(__be16, p)); +} + +static inline u32 get_unaligned_be32(const void *p) +{ + return be32_to_cpu(__get_unaligned_t(__be32, p)); +} + +static inline u64 get_unaligned_be64(const void *p) +{ + return be64_to_cpu(__get_unaligned_t(__be64, p)); +} + +static inline void put_unaligned_be16(u16 val, void *p) +{ + __put_unaligned_t(__be16, cpu_to_be16(val), p); +} + +static inline void put_unaligned_be32(u32 val, void *p) +{ + __put_unaligned_t(__be32, cpu_to_be32(val), p); +} + +static inline void put_unaligned_be64(u64 val, void *p) +{ + __put_unaligned_t(__be64, cpu_to_be64(val), p); +} + +static inline u32 __get_unaligned_be24(const u8 *p) +{ + return p[0] << 16 | p[1] << 8 | p[2]; +} + +static inline u32 get_unaligned_be24(const void *p) +{ + return __get_unaligned_be24(p); +} + +static inline u32 __get_unaligned_le24(const u8 *p) +{ + return p[0] | p[1] << 8 | p[2] << 16; +} + +static inline u32 get_unaligned_le24(const void *p) +{ + return __get_unaligned_le24(p); +} + +static inline void __put_unaligned_be24(const u32 val, u8 *p) +{ + *p++ = val >> 16; + *p++ = val >> 8; + *p++ = val; +} + +static inline void put_unaligned_be24(const u32 val, void *p) +{ + __put_unaligned_be24(val, p); +} + +static inline void __put_unaligned_le24(const u32 val, u8 *p) +{ + *p++ = val; + *p++ = val >> 8; + *p++ = val >> 16; +} + +static inline void put_unaligned_le24(const u32 val, void *p) +{ + __put_unaligned_le24(val, p); +} + +static inline void __put_unaligned_be48(const u64 val, u8 *p) +{ + *p++ = val >> 40; + *p++ = val >> 32; + *p++ = val >> 24; + *p++ = val >> 16; + *p++ = val >> 8; + *p++ = val; +} + +static inline void put_unaligned_be48(const u64 val, void *p) +{ + __put_unaligned_be48(val, p); +} + +static inline u64 __get_unaligned_be48(const u8 *p) +{ + return (u64)p[0] << 40 | (u64)p[1] << 32 | (u64)p[2] << 24 | + p[3] << 16 | p[4] << 8 | p[5]; +} + +static inline u64 get_unaligned_be48(const void *p) +{ + return __get_unaligned_be48(p); +} +#pragma GCC diagnostic pop + +#endif /* __ASM_GENERIC_UNALIGNED_H */ diff --git a/tools/lib/api/io.h b/tools/lib/api/io.h index 9fc429d2852d..a77b74c5fb65 100644 --- a/tools/lib/api/io.h +++ b/tools/lib/api/io.h @@ -180,6 +180,7 @@ static inline ssize_t io__getline(struct io *io, char **line_out, size_t *line_l return line_len; err_out: free(line); + *line_out = NULL; return -ENOMEM; } diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c index b8b066d0dc5e..3acbbccc1901 100644 --- a/tools/lib/perf/evlist.c +++ b/tools/lib/perf/evlist.c @@ -738,3 +738,12 @@ int perf_evlist__nr_groups(struct perf_evlist *evlist) } return nr_groups; } + +void perf_evlist__go_system_wide(struct perf_evlist *evlist, struct perf_evsel *evsel) +{ + if (!evsel->system_wide) { + evsel->system_wide = true; + if (evlist->needs_map_propagation) + __perf_evlist__propagate_maps(evlist, evsel); + } +} diff --git a/tools/lib/perf/include/internal/evlist.h b/tools/lib/perf/include/internal/evlist.h index 3339bc2f1765..d86ffe8ed483 100644 --- a/tools/lib/perf/include/internal/evlist.h +++ b/tools/lib/perf/include/internal/evlist.h @@ -135,4 +135,6 @@ int perf_evlist__id_add_fd(struct perf_evlist *evlist, void perf_evlist__reset_id_hash(struct perf_evlist *evlist); void __perf_evlist__set_leader(struct list_head *list, struct perf_evsel *leader); + +void perf_evlist__go_system_wide(struct perf_evlist *evlist, struct perf_evsel *evsel); #endif /* __LIBPERF_INTERNAL_EVLIST_H */ diff --git a/tools/lib/perf/include/internal/rc_check.h b/tools/lib/perf/include/internal/rc_check.h index d5d771ccdc7b..f80ddfc80129 100644 --- a/tools/lib/perf/include/internal/rc_check.h +++ b/tools/lib/perf/include/internal/rc_check.h @@ -9,8 +9,12 @@ * Enable reference count checking implicitly with leak checking, which is * integrated into address sanitizer. */ -#if defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) +#if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) #define REFCNT_CHECKING 1 +#elif defined(__has_feature) +#if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer) +#define REFCNT_CHECKING 1 +#endif #endif /* @@ -50,6 +54,9 @@ /* A put operation removing the indirection layer. */ #define RC_CHK_PUT(object) {} +/* Pointer equality when the indirection may or may not be there. */ +#define RC_CHK_EQUAL(object1, object2) (object1 == object2) + #else /* Replaces "struct foo" so that the pointer may be interposed. */ @@ -97,6 +104,10 @@ } \ } while(0) +/* Pointer equality when the indirection may or may not be there. */ +#define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \ + (object1 && object2 && object1->orig == object2->orig)) + #endif #endif /* __LIBPERF_INTERNAL_RC_CHECK_H */ diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index ca5789625cd2..8331bd28b10e 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt @@ -124,6 +124,14 @@ Options of *pipe* --loop=:: Specify number of loops. +-G:: +--cgroups=:: +Names of cgroups for sender and receiver, separated by a comma. +This is useful to check cgroup context switching overhead. +Note that perf doesn't create nor delete the cgroups, so users should +make sure that the cgroups exist and are accessible before use. + + Example of *pipe* ^^^^^^^^^^^^^^^^^ @@ -141,6 +149,17 @@ Example of *pipe* Total time:0.016 sec 16.948000 usecs/op 59004 ops/sec + +% perf bench sched pipe -G AAA,BBB +(executing 1000000 pipe operations between cgroups) +# Running 'sched/pipe' benchmark: +# Executed 1000000 pipe operations between two processes + + Total time: 6.886 [sec] + + 6.886208 usecs/op + 145217 ops/sec + --------------------- SUITES FOR 'syscall' diff --git a/tools/perf/Documentation/perf-kwork.txt b/tools/perf/Documentation/perf-kwork.txt index 3c36324712b6..109ace1d5e90 100644 --- a/tools/perf/Documentation/perf-kwork.txt +++ b/tools/perf/Documentation/perf-kwork.txt @@ -8,7 +8,7 @@ perf-kwork - Tool to trace/measure kernel work properties (latencies) SYNOPSIS -------- [verse] -'perf kwork' {record} +'perf kwork' {record|report|latency|timehist|top} DESCRIPTION ----------- @@ -23,6 +23,8 @@ There are several variants of 'perf kwork': 'perf kwork timehist' provides an analysis of kernel work events. + 'perf kwork top' to report the task cpu usage. + Example usage: perf kwork record -- sleep 1 perf kwork report @@ -30,6 +32,8 @@ There are several variants of 'perf kwork': perf kwork latency perf kwork latency -b perf kwork timehist + perf kwork top + perf kwork top -b By default it shows the individual work events such as irq, workqeueu, including the run time and delay (time between raise and actually entry): @@ -66,7 +70,7 @@ OPTIONS -k:: --kwork:: - List of kwork to profile (irq, softirq, workqueue, etc) + List of kwork to profile (irq, softirq, workqueue, sched, etc) -v:: --verbose:: @@ -175,6 +179,36 @@ OPTIONS for 'perf kwork timehist' stop time is not given (i.e, time string is 'x.y,') then analysis goes to end of file. +OPTIONS for 'perf kwork top' +--------------------------------- + +-b:: +--use-bpf:: + Use BPF to measure task cpu usage. + +-C:: +--cpu:: + Only show events for the given CPU(s) (comma separated list). + +-i:: +--input:: + Input file name. (default: perf.data unless stdin is a fifo) + +-n:: +--name:: + Only show events for the given name. + +-s:: +--sort:: + Sort by key(s): rate, runtime, tid + +--time:: + Only analyze samples within given time window: ,. Times + have the format seconds.microseconds. If start is not given (i.e., time + string is ',x.y') then analysis starts at the beginning of the file. If + stop time is not given (i.e, time string is 'x.y,') then analysis goes + to end of file. + SEE ALSO -------- linkperf:perf-record[1] diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt index 30eea576721f..503abcba1438 100644 --- a/tools/perf/Documentation/perf-lock.txt +++ b/tools/perf/Documentation/perf-lock.txt @@ -208,6 +208,13 @@ CONTENTION OPTIONS Show results using a CSV-style output to make it easy to import directly into spreadsheets. Columns are separated by the string specified in SEP. +--lock-cgroup:: + Show lock contention stat by cgroup. Requires --use-bpf. + +-G:: +--cgroup-filter=:: + Show lock contention only in the given cgroups (comma separated list). + SEE ALSO -------- diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index d5217be012d7..1889f66addf2 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -374,6 +374,9 @@ comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0- In per-thread mode with inheritance mode on (default), samples are captured only when the thread executes on the designated CPUs. Default is to monitor all CPUs. +User space tasks can migrate between CPUs, so when tracing selected CPUs, +a dummy event is created to track sideband for all CPUs. + -B:: --no-buildid:: Do not save the build ids of binaries in the perf.data files. This skips diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index d66b52407e19..b3e6ed10f40c 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -216,12 +216,6 @@ ifeq ($(call get-executable,$(BISON)),) dummy := $(error Error: $(BISON) is missing on this system, please install it) endif -ifeq ($(BUILD_BPF_SKEL),1) - ifeq ($(call get-executable,$(CLANG)),) - dummy := $(error $(CLANG) is missing on this system, please install it to be able to build with BUILD_BPF_SKEL=1) - endif -endif - ifneq ($(OUTPUT),) ifeq ($(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\).\([0-9]\+\)/\1\2\3/g') \>\= 371), 1) BISON_FILE_PREFIX_MAP := --file-prefix-map=$(OUTPUT)= @@ -530,6 +524,16 @@ ifdef CORESIGHT endif endif +ifndef NO_ZLIB + ifeq ($(feature-zlib), 1) + CFLAGS += -DHAVE_ZLIB_SUPPORT + EXTLIBS += -lz + $(call detected,CONFIG_ZLIB) + else + NO_ZLIB := 1 + endif +endif + ifndef NO_LIBELF CFLAGS += -DHAVE_LIBELF_SUPPORT EXTLIBS += -lelf @@ -571,22 +575,28 @@ ifndef NO_LIBELF ifndef NO_LIBBPF ifeq ($(feature-bpf), 1) - CFLAGS += -DHAVE_LIBBPF_SUPPORT - $(call detected,CONFIG_LIBBPF) - # detecting libbpf without LIBBPF_DYNAMIC, so make VF=1 shows libbpf detection status $(call feature_check,libbpf) ifdef LIBBPF_DYNAMIC ifeq ($(feature-libbpf), 1) EXTLIBS += -lbpf + CFLAGS += -DHAVE_LIBBPF_SUPPORT + $(call detected,CONFIG_LIBBPF) $(call detected,CONFIG_LIBBPF_DYNAMIC) else dummy := $(error Error: No libbpf devel library found or older than v1.0, please install/update libbpf-devel); endif else - # Libbpf will be built as a static library from tools/lib/bpf. - LIBBPF_STATIC := 1 + ifeq ($(NO_ZLIB), 1) + dummy := $(warning Warning: Statically building libbpf not possible as zlib is missing) + NO_LIBBPF := 1 + else + # Libbpf will be built as a static library from tools/lib/bpf. + LIBBPF_STATIC := 1 + $(call detected,CONFIG_LIBBPF) + CFLAGS += -DHAVE_LIBBPF_SUPPORT + endif endif endif endif # NO_LIBBPF @@ -663,16 +673,43 @@ ifndef NO_LIBBPF endif endif -ifdef BUILD_BPF_SKEL - $(call feature_check,clang-bpf-co-re) - ifeq ($(feature-clang-bpf-co-re), 0) - dummy := $(error Error: clang too old/not installed. Please install recent clang to build with BUILD_BPF_SKEL) - endif +ifndef BUILD_BPF_SKEL + # BPF skeletons control a large number of perf features, by default + # they are enabled. + BUILD_BPF_SKEL := 1 +endif + +ifeq ($(BUILD_BPF_SKEL),1) ifeq ($(filter -DHAVE_LIBBPF_SUPPORT, $(CFLAGS)),) - dummy := $(error Error: BPF skeleton support requires libbpf) + dummy := $(warning Warning: Disabled BPF skeletons as libbpf is required) + BUILD_BPF_SKEL := 0 + else ifeq ($(filter -DHAVE_LIBELF_SUPPORT, $(CFLAGS)),) + dummy := $(warning Warning: Disabled BPF skeletons as libelf is required by bpftool) + BUILD_BPF_SKEL := 0 + else ifeq ($(filter -DHAVE_ZLIB_SUPPORT, $(CFLAGS)),) + dummy := $(warning Warning: Disabled BPF skeletons as zlib is required by bpftool) + BUILD_BPF_SKEL := 0 + else ifeq ($(call get-executable,$(CLANG)),) + dummy := $(warning Warning: Disabled BPF skeletons as clang ($(CLANG)) is missing) + BUILD_BPF_SKEL := 0 + else + CLANG_VERSION := $(shell $(CLANG) --version | head -1 | sed 's/.*clang version \([[:digit:]]\+.[[:digit:]]\+.[[:digit:]]\+\).*/\1/g') + ifeq ($(call version-lt3,$(CLANG_VERSION),12.0.1),1) + dummy := $(warning Warning: Disabled BPF skeletons as reliable BTF generation needs at least $(CLANG) version 12.0.1) + BUILD_BPF_SKEL := 0 + endif + endif + ifeq ($(BUILD_BPF_SKEL),1) + $(call feature_check,clang-bpf-co-re) + ifeq ($(feature-clang-bpf-co-re), 0) + dummy := $(warning Warning: Disabled BPF skeletons as clang is too old) + BUILD_BPF_SKEL := 0 + endif + endif + ifeq ($(BUILD_BPF_SKEL),1) + $(call detected,CONFIG_PERF_BPF_SKEL) + CFLAGS += -DHAVE_BPF_SKEL endif - $(call detected,CONFIG_PERF_BPF_SKEL) - CFLAGS += -DHAVE_BPF_SKEL endif ifndef GEN_VMLINUX_H @@ -946,16 +983,6 @@ ifndef NO_DEMANGLE endif endif -ifndef NO_ZLIB - ifeq ($(feature-zlib), 1) - CFLAGS += -DHAVE_ZLIB_SUPPORT - EXTLIBS += -lz - $(call detected,CONFIG_ZLIB) - else - NO_ZLIB := 1 - endif -endif - ifndef NO_LZMA ifeq ($(feature-lzma), 1) CFLAGS += -DHAVE_LZMA_SUPPORT diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 14dedd11a1f5..d88da787e815 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -69,6 +69,10 @@ include ../scripts/utilities.mak # Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support # for dwarf backtrace post unwind. # +# Define NO_LIBTRACEEVENT=1 if you don't want libtraceevent to be linked, +# this will remove multiple features and tools, such as 'perf trace', +# that need it to read tracefs event format files, etc. +# # Define NO_PERF_READ_VDSO32 if you do not want to build perf-read-vdso32 # for reading the 32-bit compatibility VDSO in 64-bit mode # @@ -120,7 +124,7 @@ include ../scripts/utilities.mak # # Define NO_LIBDEBUGINFOD if you do not want support debuginfod # -# Define BUILD_BPF_SKEL to enable BPF skeletons +# Set BUILD_BPF_SKEL to 0 to override BUILD_BPF_SKEL and not build BPF skeletons # # Define BUILD_NONDISTRO to enable building an linking against libbfd and # libiberty distribution license incompatible libraries. @@ -351,10 +355,13 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so +# Use the detected configuration +-include $(OUTPUT).config-detected + ifeq ($(CONFIG_LIBTRACEEVENT),y) PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) else - PYTHON_EXT_SRCS := $(shell grep -v '^\#\|util/trace-event.c' util/python-ext-sources) + PYTHON_EXT_SRCS := $(shell grep -v ^\#\\\|util/trace-event.c util/python-ext-sources) endif PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBAPI) @@ -1043,13 +1050,14 @@ SKELETONS += $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h SKELETONS += $(SKEL_OUT)/bperf_cgroup.skel.h $(SKEL_OUT)/func_latency.skel.h SKELETONS += $(SKEL_OUT)/off_cpu.skel.h $(SKEL_OUT)/lock_contention.skel.h SKELETONS += $(SKEL_OUT)/kwork_trace.skel.h $(SKEL_OUT)/sample_filter.skel.h +SKELETONS += $(SKEL_OUT)/kwork_top.skel.h SKELETONS += $(SKEL_OUT)/bench_uprobe.skel.h SKELETONS += $(SKEL_OUT)/augmented_raw_syscalls.skel.h $(SKEL_TMP_OUT) $(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT): $(Q)$(MKDIR) -p $@ -ifdef BUILD_BPF_SKEL +ifeq ($(CONFIG_PERF_BPF_SKEL),y) BPFTOOL := $(SKEL_TMP_OUT)/bootstrap/bpftool # Get Clang's default includes on this system, as opposed to those seen by # '--target=bpf'. This fixes "missing" files on some architectures/distros, @@ -1127,11 +1135,11 @@ bpf-skel: $(SKELETONS) .PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o -else # BUILD_BPF_SKEL +else # CONFIG_PERF_BPF_SKEL bpf-skel: -endif # BUILD_BPF_SKEL +endif # CONFIG_PERF_BPF_SKEL bpf-skel-clean: $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index b8d6a953fd74..2cf873d71dff 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -205,8 +205,17 @@ static int cs_etm_validate_config(struct auxtrace_record *itr, for (i = 0; i < cpu__max_cpu().cpu; i++) { struct perf_cpu cpu = { .cpu = i, }; - if (!perf_cpu_map__has(event_cpus, cpu) || - !perf_cpu_map__has(online_cpus, cpu)) + /* + * In per-cpu case, do the validation for CPUs to work with. + * In per-thread case, the CPU map is empty. Since the traced + * program can run on any CPUs in this case, thus don't skip + * validation. + */ + if (!perf_cpu_map__empty(event_cpus) && + !perf_cpu_map__has(event_cpus, cpu)) + continue; + + if (!perf_cpu_map__has(online_cpus, cpu)) continue; err = cs_etm_validate_context_id(itr, evsel, i); @@ -433,6 +442,15 @@ static int cs_etm_recording_options(struct auxtrace_record *itr, "contextid", 1); } + /* + * When the option '--timestamp' or '-T' is enabled, the PERF_SAMPLE_TIME + * bit is set for all events. In this case, always enable Arm CoreSight + * timestamp tracing. + */ + if (opts->sample_time_set) + evsel__set_config_if_unset(cs_etm_pmu, cs_etm_evsel, + "timestamp", 1); + /* Add dummy event to keep tracking */ err = parse_event(evlist, "dummy:u"); if (err) @@ -917,16 +935,9 @@ out: * (CFG_CHG and evsel__set_config_if_unset()). If no default is set then user * changes aren't tracked. */ -struct perf_event_attr * -cs_etm_get_default_config(struct perf_pmu *pmu __maybe_unused) +void +cs_etm_get_default_config(const struct perf_pmu *pmu __maybe_unused, + struct perf_event_attr *attr) { - struct perf_event_attr *attr; - - attr = zalloc(sizeof(struct perf_event_attr)); - if (!attr) - return NULL; - attr->sample_period = 1; - - return attr; } diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c index a9623b128ece..7f3af3b97f3b 100644 --- a/tools/perf/arch/arm/util/pmu.c +++ b/tools/perf/arch/arm/util/pmu.c @@ -14,22 +14,22 @@ #include "../../../util/pmu.h" #include "../../../util/cs-etm.h" -struct perf_event_attr -*perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) +void perf_pmu__arch_init(struct perf_pmu *pmu __maybe_unused) { #ifdef HAVE_AUXTRACE_SUPPORT if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) { /* add ETM default config here */ pmu->selectable = true; - return cs_etm_get_default_config(pmu); + pmu->perf_event_attr_init_default = cs_etm_get_default_config; #if defined(__aarch64__) } else if (strstarts(pmu->name, ARM_SPE_PMU_NAME)) { - return arm_spe_pmu_default_config(pmu); + pmu->selectable = true; + pmu->is_uncore = false; + pmu->perf_event_attr_init_default = arm_spe_pmu_default_config; } else if (strstarts(pmu->name, HISI_PTT_PMU_NAME)) { pmu->selectable = true; #endif } #endif - return NULL; } diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index 9cc3d6dcb849..e3acc739bd00 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -113,6 +113,25 @@ arm_spe_snapshot_resolve_auxtrace_defaults(struct record_opts *opts, } } +static __u64 arm_spe_pmu__sample_period(const struct perf_pmu *arm_spe_pmu) +{ + static __u64 sample_period; + + if (sample_period) + return sample_period; + + /* + * If kernel driver doesn't advertise a minimum, + * use max allowable by PMSIDR_EL1.INTERVAL + */ + if (perf_pmu__scan_file(arm_spe_pmu, "caps/min_interval", "%llu", + &sample_period) != 1) { + pr_debug("arm_spe driver doesn't advertise a min. interval. Using 4096\n"); + sample_period = 4096; + } + return sample_period; +} + static int arm_spe_recording_options(struct auxtrace_record *itr, struct evlist *evlist, struct record_opts *opts) @@ -136,7 +155,7 @@ static int arm_spe_recording_options(struct auxtrace_record *itr, return -EINVAL; } evsel->core.attr.freq = 0; - evsel->core.attr.sample_period = arm_spe_pmu->default_config->sample_period; + evsel->core.attr.sample_period = arm_spe_pmu__sample_period(arm_spe_pmu); evsel->needs_auxtrace_mmap = true; arm_spe_evsel = evsel; opts->full_auxtrace = true; @@ -495,29 +514,8 @@ struct auxtrace_record *arm_spe_recording_init(int *err, return &sper->itr; } -struct perf_event_attr -*arm_spe_pmu_default_config(struct perf_pmu *arm_spe_pmu) +void +arm_spe_pmu_default_config(const struct perf_pmu *arm_spe_pmu, struct perf_event_attr *attr) { - struct perf_event_attr *attr; - - attr = zalloc(sizeof(struct perf_event_attr)); - if (!attr) { - pr_err("arm_spe default config cannot allocate a perf_event_attr\n"); - return NULL; - } - - /* - * If kernel driver doesn't advertise a minimum, - * use max allowable by PMSIDR_EL1.INTERVAL - */ - if (perf_pmu__scan_file(arm_spe_pmu, "caps/min_interval", "%llu", - &attr->sample_period) != 1) { - pr_debug("arm_spe driver doesn't advertise a min. interval. Using 4096\n"); - attr->sample_period = 4096; - } - - arm_spe_pmu->selectable = true; - arm_spe_pmu->is_uncore = false; - - return attr; + attr->sample_period = arm_spe_pmu__sample_period(arm_spe_pmu); } diff --git a/tools/perf/arch/arm64/util/pmu.c b/tools/perf/arch/arm64/util/pmu.c index 615084eb88d8..2a4eab2d160e 100644 --- a/tools/perf/arch/arm64/util/pmu.c +++ b/tools/perf/arch/arm64/util/pmu.c @@ -10,29 +10,25 @@ const struct pmu_metrics_table *pmu_metrics_table__find(void) { - struct perf_pmu *pmu = pmu__find_core_pmu(); + struct perf_pmu *pmu; + /* Metrics aren't currently supported on heterogeneous Arm systems */ + if (perf_pmus__num_core_pmus() > 1) + return NULL; + + /* Doesn't matter which one here because they'll all be the same */ + pmu = perf_pmus__find_core_pmu(); if (pmu) return perf_pmu__find_metrics_table(pmu); return NULL; } -const struct pmu_events_table *pmu_events_table__find(void) -{ - struct perf_pmu *pmu = pmu__find_core_pmu(); - - if (pmu) - return perf_pmu__find_events_table(pmu); - - return NULL; -} - double perf_pmu__cpu_slots_per_cycle(void) { char path[PATH_MAX]; unsigned long long slots = 0; - struct perf_pmu *pmu = pmu__find_core_pmu(); + struct perf_pmu *pmu = perf_pmus__find_core_pmu(); if (pmu) { perf_pmu__pathname_scnprintf(path, sizeof(path), diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c index c8d0dc775e5d..6b00efd53638 100644 --- a/tools/perf/arch/powerpc/util/header.c +++ b/tools/perf/arch/powerpc/util/header.c @@ -34,7 +34,7 @@ get_cpuid_str(struct perf_pmu *pmu __maybe_unused) { char *bufp; - if (asprintf(&bufp, "%.8lx", mfspr(SPRN_PVR)) < 0) + if (asprintf(&bufp, "0x%.8lx", mfspr(SPRN_PVR)) < 0) bufp = NULL; return bufp; diff --git a/tools/perf/arch/s390/util/pmu.c b/tools/perf/arch/s390/util/pmu.c index 11f03f32e3fd..886c30e001fa 100644 --- a/tools/perf/arch/s390/util/pmu.c +++ b/tools/perf/arch/s390/util/pmu.c @@ -13,11 +13,10 @@ #define S390_PMUPAI_EXT "pai_ext" #define S390_PMUCPUM_CF "cpum_cf" -struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu) +void perf_pmu__arch_init(struct perf_pmu *pmu) { if (!strcmp(pmu->name, S390_PMUPAI_CRYPTO) || !strcmp(pmu->name, S390_PMUPAI_EXT) || !strcmp(pmu->name, S390_PMUCPUM_CF)) pmu->selectable = true; - return NULL; } diff --git a/tools/perf/arch/x86/annotate/instructions.c b/tools/perf/arch/x86/annotate/instructions.c index 5f4ac4fc7fcf..5cdf457f5cbe 100644 --- a/tools/perf/arch/x86/annotate/instructions.c +++ b/tools/perf/arch/x86/annotate/instructions.c @@ -74,12 +74,15 @@ static struct ins x86__instructions[] = { { .name = "movdqa", .ops = &mov_ops, }, { .name = "movdqu", .ops = &mov_ops, }, { .name = "movsd", .ops = &mov_ops, }, - { .name = "movslq", .ops = &mov_ops, }, { .name = "movss", .ops = &mov_ops, }, + { .name = "movsb", .ops = &mov_ops, }, + { .name = "movsw", .ops = &mov_ops, }, + { .name = "movsl", .ops = &mov_ops, }, { .name = "movupd", .ops = &mov_ops, }, { .name = "movups", .ops = &mov_ops, }, - { .name = "movzbl", .ops = &mov_ops, }, - { .name = "movzwl", .ops = &mov_ops, }, + { .name = "movzb", .ops = &mov_ops, }, + { .name = "movzw", .ops = &mov_ops, }, + { .name = "movzl", .ops = &mov_ops, }, { .name = "mulsd", .ops = &mov_ops, }, { .name = "mulss", .ops = &mov_ops, }, { .name = "nop", .ops = &nop_ops, }, diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 31807791589e..fa0c718b9e72 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -60,36 +60,31 @@ struct intel_pt_recording { size_t priv_size; }; -static int intel_pt_parse_terms_with_default(struct perf_pmu *pmu, +static int intel_pt_parse_terms_with_default(const struct perf_pmu *pmu, const char *str, u64 *config) { - struct list_head *terms; + struct parse_events_terms terms; struct perf_event_attr attr = { .size = 0, }; int err; - terms = malloc(sizeof(struct list_head)); - if (!terms) - return -ENOMEM; - - INIT_LIST_HEAD(terms); - - err = parse_events_terms(terms, str, /*input=*/ NULL); + parse_events_terms__init(&terms); + err = parse_events_terms(&terms, str, /*input=*/ NULL); if (err) goto out_free; attr.config = *config; - err = perf_pmu__config_terms(pmu, &attr, terms, /*zero=*/true, /*err=*/NULL); + err = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/true, /*err=*/NULL); if (err) goto out_free; *config = attr.config; out_free: - parse_events_terms__delete(terms); + parse_events_terms__exit(&terms); return err; } -static int intel_pt_parse_terms(struct perf_pmu *pmu, const char *str, u64 *config) +static int intel_pt_parse_terms(const struct perf_pmu *pmu, const char *str, u64 *config) { *config = 0; return intel_pt_parse_terms_with_default(pmu, str, config); @@ -182,7 +177,7 @@ static int intel_pt_pick_bit(int bits, int target) return pick; } -static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu) +static u64 intel_pt_default_config(const struct perf_pmu *intel_pt_pmu) { char buf[256]; int mtc, mtc_periods = 0, mtc_period; @@ -261,20 +256,17 @@ static int intel_pt_parse_snapshot_options(struct auxtrace_record *itr, return 0; } -struct perf_event_attr * -intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu) +void intel_pt_pmu_default_config(const struct perf_pmu *intel_pt_pmu, + struct perf_event_attr *attr) { - struct perf_event_attr *attr; + static u64 config; + static bool initialized; - attr = zalloc(sizeof(struct perf_event_attr)); - if (!attr) - return NULL; - - attr->config = intel_pt_default_config(intel_pt_pmu); - - intel_pt_pmu->selectable = true; - - return attr; + if (!initialized) { + config = intel_pt_default_config(intel_pt_pmu); + initialized = true; + } + attr->config = config; } static const char *intel_pt_find_filter(struct evlist *evlist, diff --git a/tools/perf/arch/x86/util/pmu.c b/tools/perf/arch/x86/util/pmu.c index f428cffb0378..469555ae9b3c 100644 --- a/tools/perf/arch/x86/util/pmu.c +++ b/tools/perf/arch/x86/util/pmu.c @@ -17,158 +17,19 @@ #include "../../../util/pmus.h" #include "env.h" -struct pmu_alias { - char *name; - char *alias; - struct list_head list; -}; - -static LIST_HEAD(pmu_alias_name_list); -static bool cached_list; - -struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) +void perf_pmu__arch_init(struct perf_pmu *pmu __maybe_unused) { #ifdef HAVE_AUXTRACE_SUPPORT if (!strcmp(pmu->name, INTEL_PT_PMU_NAME)) { pmu->auxtrace = true; - return intel_pt_pmu_default_config(pmu); + pmu->selectable = true; + pmu->perf_event_attr_init_default = intel_pt_pmu_default_config; } if (!strcmp(pmu->name, INTEL_BTS_PMU_NAME)) { pmu->auxtrace = true; pmu->selectable = true; } #endif - return NULL; -} - -static void pmu_alias__delete(struct pmu_alias *pmu_alias) -{ - if (!pmu_alias) - return; - - zfree(&pmu_alias->name); - zfree(&pmu_alias->alias); - free(pmu_alias); -} - -static struct pmu_alias *pmu_alias__new(char *name, char *alias) -{ - struct pmu_alias *pmu_alias = zalloc(sizeof(*pmu_alias)); - - if (pmu_alias) { - pmu_alias->name = strdup(name); - if (!pmu_alias->name) - goto out_delete; - - pmu_alias->alias = strdup(alias); - if (!pmu_alias->alias) - goto out_delete; - } - return pmu_alias; - -out_delete: - pmu_alias__delete(pmu_alias); - return NULL; -} - -static int setup_pmu_alias_list(void) -{ - int fd, dirfd; - DIR *dir; - struct dirent *dent; - struct pmu_alias *pmu_alias; - char buf[MAX_PMU_NAME_LEN]; - FILE *file; - int ret = -ENOMEM; - - dirfd = perf_pmu__event_source_devices_fd(); - if (dirfd < 0) - return -1; - - dir = fdopendir(dirfd); - if (!dir) - return -errno; - - while ((dent = readdir(dir))) { - if (!strcmp(dent->d_name, ".") || - !strcmp(dent->d_name, "..")) - continue; - - fd = perf_pmu__pathname_fd(dirfd, dent->d_name, "alias", O_RDONLY); - if (fd < 0) - continue; - - file = fdopen(fd, "r"); - if (!file) - continue; - - if (!fgets(buf, sizeof(buf), file)) { - fclose(file); - continue; - } - - fclose(file); - - /* Remove the last '\n' */ - buf[strlen(buf) - 1] = 0; - - pmu_alias = pmu_alias__new(dent->d_name, buf); - if (!pmu_alias) - goto close_dir; - - list_add_tail(&pmu_alias->list, &pmu_alias_name_list); - } - - ret = 0; - -close_dir: - closedir(dir); - return ret; -} - -static const char *__pmu_find_real_name(const char *name) -{ - struct pmu_alias *pmu_alias; - - list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) { - if (!strcmp(name, pmu_alias->alias)) - return pmu_alias->name; - } - - return name; -} - -const char *pmu_find_real_name(const char *name) -{ - if (cached_list) - return __pmu_find_real_name(name); - - setup_pmu_alias_list(); - cached_list = true; - - return __pmu_find_real_name(name); -} - -static const char *__pmu_find_alias_name(const char *name) -{ - struct pmu_alias *pmu_alias; - - list_for_each_entry(pmu_alias, &pmu_alias_name_list, list) { - if (!strcmp(name, pmu_alias->name)) - return pmu_alias->alias; - } - return NULL; -} - -const char *pmu_find_alias_name(const char *name) -{ - if (cached_list) - return __pmu_find_alias_name(name); - - setup_pmu_alias_list(); - cached_list = true; - - return __pmu_find_alias_name(name); } int perf_pmus__num_mem_pmus(void) diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index fa1f8f998814..93dcd9dba3d0 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c @@ -36,6 +36,7 @@ static bool use_pipes = false; static unsigned int nr_loops = 100; static bool thread_mode = false; static unsigned int num_groups = 10; +static unsigned int total_children = 0; static struct list_head sender_contexts = LIST_HEAD_INIT(sender_contexts); static struct list_head receiver_contexts = LIST_HEAD_INIT(receiver_contexts); @@ -55,6 +56,13 @@ struct receiver_context { int wakefd; }; +union messaging_worker { + pthread_t thread; + pid_t pid; +}; + +static union messaging_worker *worker_tab; + static void fdpair(int fds[2]) { if (use_pipes) { @@ -98,7 +106,7 @@ static void *sender(struct sender_context *ctx) again: ret = write(ctx->out_fds[j], data + done, - sizeof(data)-done); + sizeof(data) - done); if (ret < 0) err(EXIT_FAILURE, "SENDER: write"); done += ret; @@ -139,30 +147,12 @@ again: return NULL; } -static pthread_t create_worker(void *ctx, void *(*func)(void *)) +static void create_thread_worker(union messaging_worker *worker, + void *ctx, void *(*func)(void *)) { pthread_attr_t attr; - pthread_t childid; int ret; - if (!thread_mode) { - /* process mode */ - /* Fork the receiver. */ - switch (fork()) { - case -1: - err(EXIT_FAILURE, "fork()"); - break; - case 0: - (*func) (ctx); - exit(0); - break; - default: - break; - } - - return (pthread_t)0; - } - if (pthread_attr_init(&attr) != 0) err(EXIT_FAILURE, "pthread_attr_init:"); @@ -171,15 +161,37 @@ static pthread_t create_worker(void *ctx, void *(*func)(void *)) err(EXIT_FAILURE, "pthread_attr_setstacksize"); #endif - ret = pthread_create(&childid, &attr, func, ctx); + ret = pthread_create(&worker->thread, &attr, func, ctx); if (ret != 0) err(EXIT_FAILURE, "pthread_create failed"); pthread_attr_destroy(&attr); - return childid; } -static void reap_worker(pthread_t id) +static void create_process_worker(union messaging_worker *worker, + void *ctx, void *(*func)(void *)) +{ + /* Fork the receiver. */ + worker->pid = fork(); + + if (worker->pid == -1) { + err(EXIT_FAILURE, "fork()"); + } else if (worker->pid == 0) { + (*func) (ctx); + exit(0); + } +} + +static void create_worker(union messaging_worker *worker, + void *ctx, void *(*func)(void *)) +{ + if (!thread_mode) + return create_process_worker(worker, ctx, func); + else + return create_thread_worker(worker, ctx, func); +} + +static void reap_worker(union messaging_worker *worker) { int proc_status; void *thread_status; @@ -190,19 +202,19 @@ static void reap_worker(pthread_t id) if (!WIFEXITED(proc_status)) exit(1); } else { - pthread_join(id, &thread_status); + pthread_join(worker->thread, &thread_status); } } /* One group of senders and receivers */ -static unsigned int group(pthread_t *pth, +static unsigned int group(union messaging_worker *worker, unsigned int num_fds, int ready_out, int wakefd) { unsigned int i; - struct sender_context *snd_ctx = malloc(sizeof(struct sender_context) - + num_fds * sizeof(int)); + struct sender_context *snd_ctx = malloc(sizeof(struct sender_context) + + num_fds * sizeof(int)); if (!snd_ctx) err(EXIT_FAILURE, "malloc()"); @@ -226,7 +238,7 @@ static unsigned int group(pthread_t *pth, ctx->ready_out = ready_out; ctx->wakefd = wakefd; - pth[i] = create_worker(ctx, (void *)receiver); + create_worker(worker + i, ctx, (void *)receiver); snd_ctx->out_fds[i] = fds[1]; if (!thread_mode) @@ -239,7 +251,7 @@ static unsigned int group(pthread_t *pth, snd_ctx->wakefd = wakefd; snd_ctx->num_fds = num_fds; - pth[num_fds+i] = create_worker(snd_ctx, (void *)sender); + create_worker(worker + num_fds + i, snd_ctx, (void *)sender); } /* Close the fds we have left */ @@ -251,6 +263,17 @@ static unsigned int group(pthread_t *pth, return num_fds * 2; } +static void sig_handler(int sig __maybe_unused) +{ + unsigned int i; + + /* + * When exit abnormally, kill all forked child processes. + */ + for (i = 0; i < total_children; i++) + kill(worker_tab[i].pid, SIGKILL); +} + static const struct option options[] = { OPT_BOOLEAN('p', "pipe", &use_pipes, "Use pipe() instead of socketpair()"), @@ -268,27 +291,30 @@ static const char * const bench_sched_message_usage[] = { int bench_sched_messaging(int argc, const char **argv) { - unsigned int i, total_children; + unsigned int i; struct timeval start, stop, diff; unsigned int num_fds = 20; int readyfds[2], wakefds[2]; char dummy; - pthread_t *pth_tab; struct sender_context *pos, *n; argc = parse_options(argc, argv, options, bench_sched_message_usage, 0); - pth_tab = malloc(num_fds * 2 * num_groups * sizeof(pthread_t)); - if (!pth_tab) + worker_tab = malloc(num_fds * 2 * num_groups * sizeof(union messaging_worker)); + if (!worker_tab) err(EXIT_FAILURE, "main:malloc()"); fdpair(readyfds); fdpair(wakefds); - total_children = 0; + if (!thread_mode) { + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + } + for (i = 0; i < num_groups; i++) - total_children += group(pth_tab+total_children, num_fds, + total_children += group(worker_tab + total_children, num_fds, readyfds[1], wakefds[0]); /* Wait for everyone to be ready */ @@ -304,7 +330,7 @@ int bench_sched_messaging(int argc, const char **argv) /* Reap them all */ for (i = 0; i < total_children; i++) - reap_worker(pth_tab[i]); + reap_worker(worker_tab + i); gettimeofday(&stop, NULL); @@ -332,7 +358,7 @@ int bench_sched_messaging(int argc, const char **argv) break; } - free(pth_tab); + free(worker_tab); list_for_each_entry_safe(pos, n, &sender_contexts, list) { list_del_init(&pos->list); free(pos); diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index a960e7a93aec..3af6d3c55aba 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c @@ -10,7 +10,9 @@ * Ported to perf by Hitoshi Mitake */ #include +#include #include "bench.h" +#include "util/cgroup.h" #include #include @@ -19,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +34,7 @@ struct thread_data { int nr; int pipe_read; int pipe_write; + bool cgroup_failed; pthread_t pthread; }; @@ -40,9 +44,48 @@ static int loops = LOOPS_DEFAULT; /* Use processes by default: */ static bool threaded; +static char *cgrp_names[2]; +static struct cgroup *cgrps[2]; + +static int parse_two_cgroups(const struct option *opt __maybe_unused, + const char *str, int unset __maybe_unused) +{ + char *p = strdup(str); + char *q; + int ret = -1; + + if (p == NULL) { + fprintf(stderr, "memory allocation failure\n"); + return -1; + } + + q = strchr(p, ','); + if (q == NULL) { + fprintf(stderr, "it should have two cgroup names: %s\n", p); + goto out; + } + *q = '\0'; + + cgrp_names[0] = strdup(p); + cgrp_names[1] = strdup(q + 1); + + if (cgrp_names[0] == NULL || cgrp_names[1] == NULL) { + fprintf(stderr, "memory allocation failure\n"); + goto out; + } + ret = 0; + +out: + free(p); + return ret; +} + static const struct option options[] = { OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"), + OPT_CALLBACK('G', "cgroups", NULL, "SEND,RECV", + "Put sender and receivers in given cgroups", + parse_two_cgroups), OPT_END() }; @@ -51,12 +94,89 @@ static const char * const bench_sched_pipe_usage[] = { NULL }; +static int enter_cgroup(int nr) +{ + char buf[32]; + int fd, len, ret; + int saved_errno; + struct cgroup *cgrp; + pid_t pid; + + if (cgrp_names[nr] == NULL) + return 0; + + if (cgrps[nr] == NULL) { + cgrps[nr] = cgroup__new(cgrp_names[nr], /*do_open=*/true); + if (cgrps[nr] == NULL) + goto err; + } + cgrp = cgrps[nr]; + + if (threaded) + pid = syscall(__NR_gettid); + else + pid = getpid(); + + snprintf(buf, sizeof(buf), "%d\n", pid); + len = strlen(buf); + + /* try cgroup v2 interface first */ + if (threaded) + fd = openat(cgrp->fd, "cgroup.threads", O_WRONLY); + else + fd = openat(cgrp->fd, "cgroup.procs", O_WRONLY); + + /* try cgroup v1 if failed */ + if (fd < 0 && errno == ENOENT) + fd = openat(cgrp->fd, "tasks", O_WRONLY); + + if (fd < 0) + goto err; + + ret = write(fd, buf, len); + close(fd); + + if (ret != len) { + printf("Cannot enter to cgroup: %s\n", cgrp->name); + return -1; + } + return 0; + +err: + saved_errno = errno; + printf("Failed to open cgroup file in %s\n", cgrp_names[nr]); + + if (saved_errno == ENOENT) { + char mnt[PATH_MAX]; + + if (cgroupfs_find_mountpoint(mnt, sizeof(mnt), "perf_event") == 0) + printf(" Hint: create the cgroup first, like 'mkdir %s/%s'\n", + mnt, cgrp_names[nr]); + } else if (saved_errno == EACCES && geteuid() > 0) { + printf(" Hint: try to run as root\n"); + } + + return -1; +} + +static void exit_cgroup(int nr) +{ + cgroup__put(cgrps[nr]); + free(cgrp_names[nr]); +} + static void *worker_thread(void *__tdata) { struct thread_data *td = __tdata; int m = 0, i; int ret; + ret = enter_cgroup(td->nr); + if (ret < 0) { + td->cgroup_failed = true; + return NULL; + } + for (i = 0; i < loops; i++) { if (!td->nr) { ret = read(td->pipe_read, &m, sizeof(int)); @@ -76,7 +196,8 @@ static void *worker_thread(void *__tdata) int bench_sched_pipe(int argc, const char **argv) { - struct thread_data threads[2], *td; + struct thread_data threads[2] = {}; + struct thread_data *td; int pipe_1[2], pipe_2[2]; struct timeval start, stop, diff; unsigned long long result_usec = 0; @@ -112,9 +233,7 @@ int bench_sched_pipe(int argc, const char **argv) } } - if (threaded) { - for (t = 0; t < nr_threads; t++) { td = threads + t; @@ -128,7 +247,6 @@ int bench_sched_pipe(int argc, const char **argv) ret = pthread_join(td->pthread, NULL); BUG_ON(ret); } - } else { pid = fork(); assert(pid >= 0); @@ -147,6 +265,12 @@ int bench_sched_pipe(int argc, const char **argv) gettimeofday(&stop, NULL); timersub(&stop, &start, &diff); + exit_cgroup(0); + exit_cgroup(1); + + if (threads[0].cgroup_failed || threads[1].cgroup_failed) + return 0; + switch (bench_format) { case BENCH_FORMAT_DEFAULT: printf("# Executed %d pipe operations between two %s\n\n", diff --git a/tools/perf/bench/uprobe.c b/tools/perf/bench/uprobe.c index 914c0817fe8a..5c71fdc419dd 100644 --- a/tools/perf/bench/uprobe.c +++ b/tools/perf/bench/uprobe.c @@ -89,6 +89,7 @@ static int bench_uprobe__setup_bpf_skel(enum bench_uprobe bench) return err; cleanup: bench_uprobe_bpf__destroy(skel); + skel = NULL; return err; } diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index cd381693658b..e2a40f1d9225 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c @@ -277,8 +277,10 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) char filename[PATH_MAX]; struct build_id bid; - if (dso__build_id_filename(dso, filename, sizeof(filename), false) && - filename__read_build_id(filename, &bid) == -1) { + if (!dso__build_id_filename(dso, filename, sizeof(filename), false)) + return true; + + if (filename__read_build_id(filename, &bid) == -1) { if (errno == ENOENT) return false; diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 14bf7a8429e7..f007a9b27065 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -45,6 +45,11 @@ #define PRINT_BRACKETPAIR_WIDTH 2 #define PRINT_TIME_UNIT_SEC_WIDTH 2 #define PRINT_TIME_UNIT_MESC_WIDTH 3 +#define PRINT_PID_WIDTH 7 +#define PRINT_TASK_NAME_WIDTH 16 +#define PRINT_CPU_USAGE_WIDTH 6 +#define PRINT_CPU_USAGE_DECIMAL_WIDTH 2 +#define PRINT_CPU_USAGE_HIST_WIDTH 30 #define PRINT_RUNTIME_HEADER_WIDTH (PRINT_RUNTIME_WIDTH + PRINT_TIME_UNIT_MESC_WIDTH) #define PRINT_LATENCY_HEADER_WIDTH (PRINT_LATENCY_WIDTH + PRINT_TIME_UNIT_MESC_WIDTH) #define PRINT_TIMEHIST_CPU_WIDTH (PRINT_CPU_WIDTH + PRINT_BRACKETPAIR_WIDTH) @@ -131,6 +136,34 @@ static int max_latency_cmp(struct kwork_work *l, struct kwork_work *r) return 0; } +static int cpu_usage_cmp(struct kwork_work *l, struct kwork_work *r) +{ + if (l->cpu_usage > r->cpu_usage) + return 1; + if (l->cpu_usage < r->cpu_usage) + return -1; + + return 0; +} + +static int id_or_cpu_r_cmp(struct kwork_work *l, struct kwork_work *r) +{ + if (l->id < r->id) + return 1; + if (l->id > r->id) + return -1; + + if (l->id != 0) + return 0; + + if (l->cpu < r->cpu) + return 1; + if (l->cpu > r->cpu) + return -1; + + return 0; +} + static int sort_dimension__add(struct perf_kwork *kwork __maybe_unused, const char *tok, struct list_head *list) { @@ -155,12 +188,22 @@ static int sort_dimension__add(struct perf_kwork *kwork __maybe_unused, .name = "avg", .cmp = avg_latency_cmp, }; + static struct sort_dimension rate_sort_dimension = { + .name = "rate", + .cmp = cpu_usage_cmp, + }; + static struct sort_dimension tid_sort_dimension = { + .name = "tid", + .cmp = id_or_cpu_r_cmp, + }; struct sort_dimension *available_sorts[] = { &id_sort_dimension, &max_sort_dimension, &count_sort_dimension, &runtime_sort_dimension, &avg_sort_dimension, + &rate_sort_dimension, + &tid_sort_dimension, }; if (kwork->report == KWORK_REPORT_LATENCY) @@ -361,6 +404,17 @@ static void profile_update_timespan(struct perf_kwork *kwork, kwork->timeend = sample->time; } +static bool profile_name_match(struct perf_kwork *kwork, + struct kwork_work *work) +{ + if (kwork->profile_name && work->name && + (strcmp(work->name, kwork->profile_name) != 0)) { + return false; + } + + return true; +} + static bool profile_event_match(struct perf_kwork *kwork, struct kwork_work *work, struct perf_sample *sample) @@ -376,10 +430,14 @@ static bool profile_event_match(struct perf_kwork *kwork, ((ptime->end != 0) && (ptime->end < time))) return false; - if ((kwork->profile_name != NULL) && - (work->name != NULL) && - (strcmp(work->name, kwork->profile_name) != 0)) + /* + * report top needs to collect the runtime of all tasks to + * calculate the load of each core. + */ + if ((kwork->report != KWORK_REPORT_TOP) && + !profile_name_match(kwork, work)) { return false; + } profile_update_timespan(kwork, sample); return true; @@ -392,13 +450,14 @@ static int work_push_atom(struct perf_kwork *kwork, struct evsel *evsel, struct perf_sample *sample, struct machine *machine, - struct kwork_work **ret_work) + struct kwork_work **ret_work, + bool overwrite) { - struct kwork_atom *atom, *dst_atom; + struct kwork_atom *atom, *dst_atom, *last_atom; struct kwork_work *work, key; BUG_ON(class->work_init == NULL); - class->work_init(class, &key, evsel, sample, machine); + class->work_init(kwork, class, &key, src_type, evsel, sample, machine); atom = atom_new(kwork, sample); if (atom == NULL) @@ -406,12 +465,14 @@ static int work_push_atom(struct perf_kwork *kwork, work = work_findnew(&class->work_root, &key, &kwork->cmp_id); if (work == NULL) { - free(atom); + atom_free(atom); return -1; } - if (!profile_event_match(kwork, work, sample)) + if (!profile_event_match(kwork, work, sample)) { + atom_free(atom); return 0; + } if (dst_type < KWORK_TRACE_MAX) { dst_atom = list_last_entry_or_null(&work->atom_list[dst_type], @@ -425,6 +486,17 @@ static int work_push_atom(struct perf_kwork *kwork, if (ret_work != NULL) *ret_work = work; + if (overwrite) { + last_atom = list_last_entry_or_null(&work->atom_list[src_type], + struct kwork_atom, list); + if (last_atom) { + atom_del(last_atom); + + kwork->nr_skipped_events[src_type]++; + kwork->nr_skipped_events[KWORK_TRACE_MAX]++; + } + } + list_add_tail(&atom->list, &work->atom_list[src_type]); return 0; @@ -443,7 +515,7 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, struct kwork_work *work, key; BUG_ON(class->work_init == NULL); - class->work_init(class, &key, evsel, sample, machine); + class->work_init(kwork, class, &key, src_type, evsel, sample, machine); work = work_findnew(&class->work_root, &key, &kwork->cmp_id); if (ret_work != NULL) @@ -471,6 +543,38 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, return NULL; } +static struct kwork_work *find_work_by_id(struct rb_root_cached *root, + u64 id, int cpu) +{ + struct rb_node *next; + struct kwork_work *work; + + next = rb_first_cached(root); + while (next) { + work = rb_entry(next, struct kwork_work, node); + if ((cpu != -1 && work->id == id && work->cpu == cpu) || + (cpu == -1 && work->id == id)) + return work; + + next = rb_next(next); + } + + return NULL; +} + +static struct kwork_class *get_kwork_class(struct perf_kwork *kwork, + enum kwork_class_type type) +{ + struct kwork_class *class; + + list_for_each_entry(class, &kwork->class_list, list) { + if (class->type == type) + return class; + } + + return NULL; +} + static void report_update_exit_event(struct kwork_work *work, struct kwork_atom *atom, struct perf_sample *sample) @@ -500,7 +604,7 @@ static int report_entry_event(struct perf_kwork *kwork, { return work_push_atom(kwork, class, KWORK_TRACE_ENTRY, KWORK_TRACE_MAX, evsel, sample, - machine, NULL); + machine, NULL, true); } static int report_exit_event(struct perf_kwork *kwork, @@ -555,7 +659,7 @@ static int latency_raise_event(struct perf_kwork *kwork, { return work_push_atom(kwork, class, KWORK_TRACE_RAISE, KWORK_TRACE_MAX, evsel, sample, - machine, NULL); + machine, NULL, true); } static int latency_entry_event(struct perf_kwork *kwork, @@ -714,7 +818,7 @@ static int timehist_raise_event(struct perf_kwork *kwork, { return work_push_atom(kwork, class, KWORK_TRACE_RAISE, KWORK_TRACE_MAX, evsel, sample, - machine, NULL); + machine, NULL, true); } static int timehist_entry_event(struct perf_kwork *kwork, @@ -728,7 +832,7 @@ static int timehist_entry_event(struct perf_kwork *kwork, ret = work_push_atom(kwork, class, KWORK_TRACE_ENTRY, KWORK_TRACE_RAISE, evsel, sample, - machine, &work); + machine, &work, true); if (ret) return ret; @@ -775,6 +879,84 @@ out: return ret; } +static void top_update_runtime(struct kwork_work *work, + struct kwork_atom *atom, + struct perf_sample *sample) +{ + u64 delta; + u64 exit_time = sample->time; + u64 entry_time = atom->time; + + if ((entry_time != 0) && (exit_time >= entry_time)) { + delta = exit_time - entry_time; + work->total_runtime += delta; + } +} + +static int top_entry_event(struct perf_kwork *kwork, + struct kwork_class *class, + struct evsel *evsel, + struct perf_sample *sample, + struct machine *machine) +{ + return work_push_atom(kwork, class, KWORK_TRACE_ENTRY, + KWORK_TRACE_MAX, evsel, sample, + machine, NULL, true); +} + +static int top_exit_event(struct perf_kwork *kwork, + struct kwork_class *class, + struct evsel *evsel, + struct perf_sample *sample, + struct machine *machine) +{ + struct kwork_work *work, *sched_work; + struct kwork_class *sched_class; + struct kwork_atom *atom; + + atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT, + KWORK_TRACE_ENTRY, evsel, sample, + machine, &work); + if (!work) + return -1; + + if (atom) { + sched_class = get_kwork_class(kwork, KWORK_CLASS_SCHED); + if (sched_class) { + sched_work = find_work_by_id(&sched_class->work_root, + work->id, work->cpu); + if (sched_work) + top_update_runtime(work, atom, sample); + } + atom_del(atom); + } + + return 0; +} + +static int top_sched_switch_event(struct perf_kwork *kwork, + struct kwork_class *class, + struct evsel *evsel, + struct perf_sample *sample, + struct machine *machine) +{ + struct kwork_atom *atom; + struct kwork_work *work; + + atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT, + KWORK_TRACE_ENTRY, evsel, sample, + machine, &work); + if (!work) + return -1; + + if (atom) { + top_update_runtime(work, atom, sample); + atom_del(atom); + } + + return top_entry_event(kwork, class, evsel, sample, machine); +} + static struct kwork_class kwork_irq; static int process_irq_handler_entry_event(struct perf_tool *tool, struct evsel *evsel, @@ -819,16 +1001,24 @@ static int irq_class_init(struct kwork_class *class, return 0; } -static void irq_work_init(struct kwork_class *class, +static void irq_work_init(struct perf_kwork *kwork, + struct kwork_class *class, struct kwork_work *work, + enum kwork_trace_type src_type __maybe_unused, struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { work->class = class; work->cpu = sample->cpu; - work->id = evsel__intval(evsel, sample, "irq"); - work->name = evsel__strval(evsel, sample, "name"); + + if (kwork->report == KWORK_REPORT_TOP) { + work->id = evsel__intval_common(evsel, sample, "common_pid"); + work->name = NULL; + } else { + work->id = evsel__intval(evsel, sample, "irq"); + work->name = evsel__strval(evsel, sample, "name"); + } } static void irq_work_name(struct kwork_work *work, char *buf, int len) @@ -938,18 +1128,27 @@ static char *evsel__softirq_name(struct evsel *evsel, u64 num) return name; } -static void softirq_work_init(struct kwork_class *class, +static void softirq_work_init(struct perf_kwork *kwork, + struct kwork_class *class, struct kwork_work *work, + enum kwork_trace_type src_type __maybe_unused, struct evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused) { - u64 num = evsel__intval(evsel, sample, "vec"); + u64 num; - work->id = num; work->class = class; work->cpu = sample->cpu; - work->name = evsel__softirq_name(evsel, num); + + if (kwork->report == KWORK_REPORT_TOP) { + work->id = evsel__intval_common(evsel, sample, "common_pid"); + work->name = NULL; + } else { + num = evsel__intval(evsel, sample, "vec"); + work->id = num; + work->name = evsel__softirq_name(evsel, num); + } } static void softirq_work_name(struct kwork_work *work, char *buf, int len) @@ -1029,8 +1228,10 @@ static int workqueue_class_init(struct kwork_class *class, return 0; } -static void workqueue_work_init(struct kwork_class *class, +static void workqueue_work_init(struct perf_kwork *kwork __maybe_unused, + struct kwork_class *class, struct kwork_work *work, + enum kwork_trace_type src_type __maybe_unused, struct evsel *evsel, struct perf_sample *sample, struct machine *machine) @@ -1064,10 +1265,77 @@ static struct kwork_class kwork_workqueue = { .work_name = workqueue_work_name, }; +static struct kwork_class kwork_sched; +static int process_sched_switch_event(struct perf_tool *tool, + struct evsel *evsel, + struct perf_sample *sample, + struct machine *machine) +{ + struct perf_kwork *kwork = container_of(tool, struct perf_kwork, tool); + + if (kwork->tp_handler->sched_switch_event) + return kwork->tp_handler->sched_switch_event(kwork, &kwork_sched, + evsel, sample, machine); + return 0; +} + +const struct evsel_str_handler sched_tp_handlers[] = { + { "sched:sched_switch", process_sched_switch_event, }, +}; + +static int sched_class_init(struct kwork_class *class, + struct perf_session *session) +{ + if (perf_session__set_tracepoints_handlers(session, + sched_tp_handlers)) { + pr_err("Failed to set sched tracepoints handlers\n"); + return -1; + } + + class->work_root = RB_ROOT_CACHED; + return 0; +} + +static void sched_work_init(struct perf_kwork *kwork __maybe_unused, + struct kwork_class *class, + struct kwork_work *work, + enum kwork_trace_type src_type, + struct evsel *evsel, + struct perf_sample *sample, + struct machine *machine __maybe_unused) +{ + work->class = class; + work->cpu = sample->cpu; + + if (src_type == KWORK_TRACE_EXIT) { + work->id = evsel__intval(evsel, sample, "prev_pid"); + work->name = strdup(evsel__strval(evsel, sample, "prev_comm")); + } else if (src_type == KWORK_TRACE_ENTRY) { + work->id = evsel__intval(evsel, sample, "next_pid"); + work->name = strdup(evsel__strval(evsel, sample, "next_comm")); + } +} + +static void sched_work_name(struct kwork_work *work, char *buf, int len) +{ + snprintf(buf, len, "%s", work->name); +} + +static struct kwork_class kwork_sched = { + .name = "sched", + .type = KWORK_CLASS_SCHED, + .nr_tracepoints = ARRAY_SIZE(sched_tp_handlers), + .tp_handlers = sched_tp_handlers, + .class_init = sched_class_init, + .work_init = sched_work_init, + .work_name = sched_work_name, +}; + static struct kwork_class *kwork_class_supported_list[KWORK_CLASS_MAX] = { [KWORK_CLASS_IRQ] = &kwork_irq, [KWORK_CLASS_SOFTIRQ] = &kwork_softirq, [KWORK_CLASS_WORKQUEUE] = &kwork_workqueue, + [KWORK_CLASS_SCHED] = &kwork_sched, }; static void print_separator(int len) @@ -1291,11 +1559,132 @@ static void print_bad_events(struct perf_kwork *kwork) } } -static void work_sort(struct perf_kwork *kwork, struct kwork_class *class) +const char *graph_load = "||||||||||||||||||||||||||||||||||||||||||||||||"; +const char *graph_idle = " "; +static void top_print_per_cpu_load(struct perf_kwork *kwork) +{ + int i, load_width; + u64 total, load, load_ratio; + struct kwork_top_stat *stat = &kwork->top_stat; + + for (i = 0; i < MAX_NR_CPUS; i++) { + total = stat->cpus_runtime[i].total; + load = stat->cpus_runtime[i].load; + if (test_bit(i, stat->all_cpus_bitmap) && total) { + load_ratio = load * 10000 / total; + load_width = PRINT_CPU_USAGE_HIST_WIDTH * + load_ratio / 10000; + + printf("%%Cpu%-*d[%.*s%.*s %*.*f%%]\n", + PRINT_CPU_WIDTH, i, + load_width, graph_load, + PRINT_CPU_USAGE_HIST_WIDTH - load_width, + graph_idle, + PRINT_CPU_USAGE_WIDTH, + PRINT_CPU_USAGE_DECIMAL_WIDTH, + (double)load_ratio / 100); + } + } +} + +static void top_print_cpu_usage(struct perf_kwork *kwork) +{ + struct kwork_top_stat *stat = &kwork->top_stat; + u64 idle_time = stat->cpus_runtime[MAX_NR_CPUS].idle; + u64 hardirq_time = stat->cpus_runtime[MAX_NR_CPUS].irq; + u64 softirq_time = stat->cpus_runtime[MAX_NR_CPUS].softirq; + int cpus_nr = bitmap_weight(stat->all_cpus_bitmap, MAX_NR_CPUS); + u64 cpus_total_time = stat->cpus_runtime[MAX_NR_CPUS].total; + + printf("Total : %*.*f ms, %d cpus\n", + PRINT_RUNTIME_WIDTH, RPINT_DECIMAL_WIDTH, + (double)cpus_total_time / NSEC_PER_MSEC, + cpus_nr); + + printf("%%Cpu(s): %*.*f%% id, %*.*f%% hi, %*.*f%% si\n", + PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH, + cpus_total_time ? (double)idle_time * 100 / cpus_total_time : 0, + + PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH, + cpus_total_time ? (double)hardirq_time * 100 / cpus_total_time : 0, + + PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH, + cpus_total_time ? (double)softirq_time * 100 / cpus_total_time : 0); + + top_print_per_cpu_load(kwork); +} + +static void top_print_header(struct perf_kwork *kwork __maybe_unused) +{ + int ret; + + printf("\n "); + ret = printf(" %*s %s%*s%s %*s %*s %-*s", + PRINT_PID_WIDTH, "PID", + + kwork->use_bpf ? " " : "", + kwork->use_bpf ? PRINT_PID_WIDTH : 0, + kwork->use_bpf ? "SPID" : "", + kwork->use_bpf ? " " : "", + + PRINT_CPU_USAGE_WIDTH, "%CPU", + PRINT_RUNTIME_HEADER_WIDTH + RPINT_DECIMAL_WIDTH, "RUNTIME", + PRINT_TASK_NAME_WIDTH, "COMMAND"); + printf("\n "); + print_separator(ret); +} + +static int top_print_work(struct perf_kwork *kwork __maybe_unused, struct kwork_work *work) +{ + int ret = 0; + + printf(" "); + + /* + * pid + */ + ret += printf(" %*ld ", PRINT_PID_WIDTH, work->id); + + /* + * tgid + */ + if (kwork->use_bpf) + ret += printf(" %*d ", PRINT_PID_WIDTH, work->tgid); + + /* + * cpu usage + */ + ret += printf(" %*.*f ", + PRINT_CPU_USAGE_WIDTH, PRINT_CPU_USAGE_DECIMAL_WIDTH, + (double)work->cpu_usage / 100); + + /* + * total runtime + */ + ret += printf(" %*.*f ms ", + PRINT_RUNTIME_WIDTH + RPINT_DECIMAL_WIDTH, RPINT_DECIMAL_WIDTH, + (double)work->total_runtime / NSEC_PER_MSEC); + + /* + * command + */ + if (kwork->use_bpf) + ret += printf(" %s%s%s", + work->is_kthread ? "[" : "", + work->name, + work->is_kthread ? "]" : ""); + else + ret += printf(" %-*s", PRINT_TASK_NAME_WIDTH, work->name); + + printf("\n"); + return ret; +} + +static void work_sort(struct perf_kwork *kwork, + struct kwork_class *class, struct rb_root_cached *root) { struct rb_node *node; struct kwork_work *data; - struct rb_root_cached *root = &class->work_root; pr_debug("Sorting %s ...\n", class->name); for (;;) { @@ -1315,7 +1704,7 @@ static void perf_kwork__sort(struct perf_kwork *kwork) struct kwork_class *class; list_for_each_entry(class, &kwork->class_list, list) - work_sort(kwork, class); + work_sort(kwork, class, &class->work_root); } static int perf_kwork__check_config(struct perf_kwork *kwork, @@ -1338,6 +1727,11 @@ static int perf_kwork__check_config(struct perf_kwork *kwork, .entry_event = timehist_entry_event, .exit_event = timehist_exit_event, }; + static struct trace_kwork_handler top_ops = { + .entry_event = timehist_entry_event, + .exit_event = top_exit_event, + .sched_switch_event = top_sched_switch_event, + }; switch (kwork->report) { case KWORK_REPORT_RUNTIME: @@ -1349,6 +1743,9 @@ static int perf_kwork__check_config(struct perf_kwork *kwork, case KWORK_REPORT_TIMEHIST: kwork->tp_handler = &timehist_ops; break; + case KWORK_REPORT_TOP: + kwork->tp_handler = &top_ops; + break; default: pr_debug("Invalid report type %d\n", kwork->report); return -1; @@ -1469,7 +1866,7 @@ static void sig_handler(int sig) * Simply capture termination signal so that * the program can continue after pause returns */ - pr_debug("Captuer signal %d\n", sig); + pr_debug("Capture signal %d\n", sig); } static int perf_kwork__report_bpf(struct perf_kwork *kwork) @@ -1595,6 +1992,248 @@ static int perf_kwork__timehist(struct perf_kwork *kwork) return perf_kwork__read_events(kwork); } +static void top_calc_total_runtime(struct perf_kwork *kwork) +{ + struct kwork_class *class; + struct kwork_work *work; + struct rb_node *next; + struct kwork_top_stat *stat = &kwork->top_stat; + + class = get_kwork_class(kwork, KWORK_CLASS_SCHED); + if (!class) + return; + + next = rb_first_cached(&class->work_root); + while (next) { + work = rb_entry(next, struct kwork_work, node); + BUG_ON(work->cpu >= MAX_NR_CPUS); + stat->cpus_runtime[work->cpu].total += work->total_runtime; + stat->cpus_runtime[MAX_NR_CPUS].total += work->total_runtime; + next = rb_next(next); + } +} + +static void top_calc_idle_time(struct perf_kwork *kwork, + struct kwork_work *work) +{ + struct kwork_top_stat *stat = &kwork->top_stat; + + if (work->id == 0) { + stat->cpus_runtime[work->cpu].idle += work->total_runtime; + stat->cpus_runtime[MAX_NR_CPUS].idle += work->total_runtime; + } +} + +static void top_calc_irq_runtime(struct perf_kwork *kwork, + enum kwork_class_type type, + struct kwork_work *work) +{ + struct kwork_top_stat *stat = &kwork->top_stat; + + if (type == KWORK_CLASS_IRQ) { + stat->cpus_runtime[work->cpu].irq += work->total_runtime; + stat->cpus_runtime[MAX_NR_CPUS].irq += work->total_runtime; + } else if (type == KWORK_CLASS_SOFTIRQ) { + stat->cpus_runtime[work->cpu].softirq += work->total_runtime; + stat->cpus_runtime[MAX_NR_CPUS].softirq += work->total_runtime; + } +} + +static void top_subtract_irq_runtime(struct perf_kwork *kwork, + struct kwork_work *work) +{ + struct kwork_class *class; + struct kwork_work *data; + unsigned int i; + int irq_class_list[] = {KWORK_CLASS_IRQ, KWORK_CLASS_SOFTIRQ}; + + for (i = 0; i < ARRAY_SIZE(irq_class_list); i++) { + class = get_kwork_class(kwork, irq_class_list[i]); + if (!class) + continue; + + data = find_work_by_id(&class->work_root, + work->id, work->cpu); + if (!data) + continue; + + if (work->total_runtime > data->total_runtime) { + work->total_runtime -= data->total_runtime; + top_calc_irq_runtime(kwork, irq_class_list[i], data); + } + } +} + +static void top_calc_cpu_usage(struct perf_kwork *kwork) +{ + struct kwork_class *class; + struct kwork_work *work; + struct rb_node *next; + struct kwork_top_stat *stat = &kwork->top_stat; + + class = get_kwork_class(kwork, KWORK_CLASS_SCHED); + if (!class) + return; + + next = rb_first_cached(&class->work_root); + while (next) { + work = rb_entry(next, struct kwork_work, node); + + if (work->total_runtime == 0) + goto next; + + __set_bit(work->cpu, stat->all_cpus_bitmap); + + top_subtract_irq_runtime(kwork, work); + + work->cpu_usage = work->total_runtime * 10000 / + stat->cpus_runtime[work->cpu].total; + + top_calc_idle_time(kwork, work); +next: + next = rb_next(next); + } +} + +static void top_calc_load_runtime(struct perf_kwork *kwork, + struct kwork_work *work) +{ + struct kwork_top_stat *stat = &kwork->top_stat; + + if (work->id != 0) { + stat->cpus_runtime[work->cpu].load += work->total_runtime; + stat->cpus_runtime[MAX_NR_CPUS].load += work->total_runtime; + } +} + +static void top_merge_tasks(struct perf_kwork *kwork) +{ + struct kwork_work *merged_work, *data; + struct kwork_class *class; + struct rb_node *node; + int cpu; + struct rb_root_cached merged_root = RB_ROOT_CACHED; + + class = get_kwork_class(kwork, KWORK_CLASS_SCHED); + if (!class) + return; + + for (;;) { + node = rb_first_cached(&class->work_root); + if (!node) + break; + + rb_erase_cached(node, &class->work_root); + data = rb_entry(node, struct kwork_work, node); + + if (!profile_name_match(kwork, data)) + continue; + + cpu = data->cpu; + merged_work = find_work_by_id(&merged_root, data->id, + data->id == 0 ? cpu : -1); + if (!merged_work) { + work_insert(&merged_root, data, &kwork->cmp_id); + } else { + merged_work->total_runtime += data->total_runtime; + merged_work->cpu_usage += data->cpu_usage; + } + + top_calc_load_runtime(kwork, data); + } + + work_sort(kwork, class, &merged_root); +} + +static void perf_kwork__top_report(struct perf_kwork *kwork) +{ + struct kwork_work *work; + struct rb_node *next; + + printf("\n"); + + top_print_cpu_usage(kwork); + top_print_header(kwork); + next = rb_first_cached(&kwork->sorted_work_root); + while (next) { + work = rb_entry(next, struct kwork_work, node); + process_skipped_events(kwork, work); + + if (work->total_runtime == 0) + goto next; + + top_print_work(kwork, work); + +next: + next = rb_next(next); + } + + printf("\n"); +} + +static int perf_kwork__top_bpf(struct perf_kwork *kwork) +{ + int ret; + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + ret = perf_kwork__top_prepare_bpf(kwork); + if (ret) + return -1; + + printf("Starting trace, Hit to stop and report\n"); + + perf_kwork__top_start(); + + /* + * a simple pause, wait here for stop signal + */ + pause(); + + perf_kwork__top_finish(); + + perf_kwork__top_read_bpf(kwork); + + perf_kwork__top_cleanup_bpf(); + + return 0; + +} + +static int perf_kwork__top(struct perf_kwork *kwork) +{ + struct __top_cpus_runtime *cpus_runtime; + int ret = 0; + + cpus_runtime = zalloc(sizeof(struct __top_cpus_runtime) * (MAX_NR_CPUS + 1)); + if (!cpus_runtime) + return -1; + + kwork->top_stat.cpus_runtime = cpus_runtime; + bitmap_zero(kwork->top_stat.all_cpus_bitmap, MAX_NR_CPUS); + + if (kwork->use_bpf) + ret = perf_kwork__top_bpf(kwork); + else + ret = perf_kwork__read_events(kwork); + + if (ret) + goto out; + + top_calc_total_runtime(kwork); + top_calc_cpu_usage(kwork); + top_merge_tasks(kwork); + + setup_pager(); + + perf_kwork__top_report(kwork); + +out: + free(kwork->top_stat.cpus_runtime); + return ret; +} + static void setup_event_list(struct perf_kwork *kwork, const struct option *options, const char * const usage_msg[]) @@ -1603,8 +2242,11 @@ static void setup_event_list(struct perf_kwork *kwork, struct kwork_class *class; char *tmp, *tok, *str; + /* + * set default events list if not specified + */ if (kwork->event_list_str == NULL) - goto null_event_list_str; + kwork->event_list_str = "irq, softirq, workqueue"; str = strdup(kwork->event_list_str); for (tok = strtok_r(str, ", ", &tmp); @@ -1623,17 +2265,6 @@ static void setup_event_list(struct perf_kwork *kwork, } free(str); -null_event_list_str: - /* - * config all kwork events if not specified - */ - if (list_empty(&kwork->class_list)) { - for (i = 0; i < KWORK_CLASS_MAX; i++) { - list_add_tail(&kwork_class_supported_list[i]->list, - &kwork->class_list); - } - } - pr_debug("Config event list:"); list_for_each_entry(class, &kwork->class_list, list) pr_debug(" %s", class->name); @@ -1692,9 +2323,10 @@ int cmd_kwork(int argc, const char **argv) static struct perf_kwork kwork = { .class_list = LIST_HEAD_INIT(kwork.class_list), .tool = { - .mmap = perf_event__process_mmap, - .mmap2 = perf_event__process_mmap2, - .sample = perf_kwork__process_tracepoint_sample, + .mmap = perf_event__process_mmap, + .mmap2 = perf_event__process_mmap2, + .sample = perf_kwork__process_tracepoint_sample, + .ordered_events = true, }, .atom_page_list = LIST_HEAD_INIT(kwork.atom_page_list), .sort_list = LIST_HEAD_INIT(kwork.sort_list), @@ -1721,13 +2353,14 @@ int cmd_kwork(int argc, const char **argv) }; static const char default_report_sort_order[] = "runtime, max, count"; static const char default_latency_sort_order[] = "avg, max, count"; + static const char default_top_sort_order[] = "rate, runtime"; const struct option kwork_options[] = { OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_STRING('k', "kwork", &kwork.event_list_str, "kwork", - "list of kwork to profile (irq, softirq, workqueue, etc)"), + "list of kwork to profile (irq, softirq, workqueue, sched, etc)"), OPT_BOOLEAN('f', "force", &kwork.force, "don't complain, do it"), OPT_END() }; @@ -1788,6 +2421,23 @@ int cmd_kwork(int argc, const char **argv) "input file name"), OPT_PARENT(kwork_options) }; + const struct option top_options[] = { + OPT_STRING('s', "sort", &kwork.sort_order, "key[,key2...]", + "sort by key(s): rate, runtime, tid"), + OPT_STRING('C', "cpu", &kwork.cpu_list, "cpu", + "list of cpus to profile"), + OPT_STRING('n', "name", &kwork.profile_name, "name", + "event name to profile"), + OPT_STRING(0, "time", &kwork.time_str, "str", + "Time span for analysis (start,stop)"), + OPT_STRING('i', "input", &input_name, "file", + "input file name"), +#ifdef HAVE_BPF_SKEL + OPT_BOOLEAN('b', "use-bpf", &kwork.use_bpf, + "Use BPF to measure task cpu usage"), +#endif + OPT_PARENT(kwork_options) + }; const char *kwork_usage[] = { NULL, NULL @@ -1804,8 +2454,12 @@ int cmd_kwork(int argc, const char **argv) "perf kwork timehist []", NULL }; + const char * const top_usage[] = { + "perf kwork top []", + NULL + }; const char *const kwork_subcommands[] = { - "record", "report", "latency", "timehist", NULL + "record", "report", "latency", "timehist", "top", NULL }; argc = parse_options_subcommand(argc, argv, kwork_options, @@ -1814,12 +2468,12 @@ int cmd_kwork(int argc, const char **argv) if (!argc) usage_with_options(kwork_usage, kwork_options); - setup_event_list(&kwork, kwork_options, kwork_usage); sort_dimension__add(&kwork, "id", &kwork.cmp_id); - if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) + if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) { + setup_event_list(&kwork, kwork_options, kwork_usage); return perf_kwork__record(&kwork, argc, argv); - else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) { + } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) { kwork.sort_order = default_report_sort_order; if (argc > 1) { argc = parse_options(argc, argv, report_options, report_usage, 0); @@ -1828,6 +2482,7 @@ int cmd_kwork(int argc, const char **argv) } kwork.report = KWORK_REPORT_RUNTIME; setup_sorting(&kwork, report_options, report_usage); + setup_event_list(&kwork, kwork_options, kwork_usage); return perf_kwork__report(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) { kwork.sort_order = default_latency_sort_order; @@ -1838,6 +2493,7 @@ int cmd_kwork(int argc, const char **argv) } kwork.report = KWORK_REPORT_LATENCY; setup_sorting(&kwork, latency_options, latency_usage); + setup_event_list(&kwork, kwork_options, kwork_usage); return perf_kwork__report(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("timehist", argv[0])) { if (argc > 1) { @@ -1846,7 +2502,21 @@ int cmd_kwork(int argc, const char **argv) usage_with_options(timehist_usage, timehist_options); } kwork.report = KWORK_REPORT_TIMEHIST; + setup_event_list(&kwork, kwork_options, kwork_usage); return perf_kwork__timehist(&kwork); + } else if (strlen(argv[0]) > 2 && strstarts("top", argv[0])) { + kwork.sort_order = default_top_sort_order; + if (argc > 1) { + argc = parse_options(argc, argv, top_options, top_usage, 0); + if (argc) + usage_with_options(top_usage, top_options); + } + kwork.report = KWORK_REPORT_TOP; + if (!kwork.event_list_str) + kwork.event_list_str = "sched, irq, softirq"; + setup_event_list(&kwork, kwork_options, kwork_usage); + setup_sorting(&kwork, top_options, top_usage); + return perf_kwork__top(&kwork); } else usage_with_options(kwork_usage, kwork_options); diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index b141f2134274..a3ff2f4edbaa 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -10,6 +10,7 @@ #include "util/thread.h" #include "util/header.h" #include "util/target.h" +#include "util/cgroup.h" #include "util/callchain.h" #include "util/lock-contention.h" #include "util/bpf_skel/lock_data.h" @@ -60,6 +61,7 @@ static bool combine_locks; static bool show_thread_stats; static bool show_lock_addrs; static bool show_lock_owner; +static bool show_lock_cgroups; static bool use_bpf; static unsigned long bpf_map_entries = MAX_ENTRIES; static int max_stack_depth = CONTENTION_STACK_DEPTH; @@ -524,6 +526,7 @@ bool match_callstack_filter(struct machine *machine, u64 *callstack) struct map *kmap; struct symbol *sym; u64 ip; + const char *arch = perf_env__arch(machine->env); if (list_empty(&callstack_filters)) return true; @@ -531,7 +534,21 @@ bool match_callstack_filter(struct machine *machine, u64 *callstack) for (int i = 0; i < max_stack_depth; i++) { struct callstack_filter *filter; - if (!callstack || !callstack[i]) + /* + * In powerpc, the callchain saved by kernel always includes + * first three entries as the NIP (next instruction pointer), + * LR (link register), and the contents of LR save area in the + * second stack frame. In certain scenarios its possible to have + * invalid kernel instruction addresses in either LR or the second + * stack frame's LR. In that case, kernel will store that address as + * zero. + * + * The below check will continue to look into callstack, + * incase first or second callstack index entry has 0 + * address for powerpc. + */ + if (!callstack || (!callstack[i] && (strcmp(arch, "powerpc") || + (i != 1 && i != 2)))) break; ip = callstack[i]; @@ -619,6 +636,7 @@ static int get_key_by_aggr_mode_simple(u64 *key, u64 addr, u32 tid) *key = tid; break; case LOCK_AGGR_CALLER: + case LOCK_AGGR_CGROUP: default: pr_err("Invalid aggregation mode: %d\n", aggr_mode); return -EINVAL; @@ -1103,6 +1121,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel, if (lock_contention_caller(evsel, sample, buf, sizeof(buf)) < 0) name = "Unknown"; break; + case LOCK_AGGR_CGROUP: case LOCK_AGGR_TASK: default: break; @@ -1628,6 +1647,9 @@ static void lock_filter_finish(void) zfree(&filters.syms); filters.nr_syms = 0; + + zfree(&filters.cgrps); + filters.nr_cgrps = 0; } static void sort_contention_result(void) @@ -1653,6 +1675,9 @@ static void print_header_stdio(void) case LOCK_AGGR_ADDR: fprintf(lock_output, " %16s %s\n\n", "address", "symbol"); break; + case LOCK_AGGR_CGROUP: + fprintf(lock_output, " %s\n\n", "cgroup"); + break; default: break; } @@ -1680,6 +1705,9 @@ static void print_header_csv(const char *sep) case LOCK_AGGR_ADDR: fprintf(lock_output, "%s%s %s%s %s\n", "address", sep, "symbol", sep, "type"); break; + case LOCK_AGGR_CGROUP: + fprintf(lock_output, "%s\n", "cgroup"); + break; default: break; } @@ -1720,6 +1748,9 @@ static void print_lock_stat_stdio(struct lock_contention *con, struct lock_stat fprintf(lock_output, " %016llx %s (%s)\n", (unsigned long long)st->addr, st->name, get_type_name(st->flags)); break; + case LOCK_AGGR_CGROUP: + fprintf(lock_output, " %s\n", st->name); + break; default: break; } @@ -1770,6 +1801,9 @@ static void print_lock_stat_csv(struct lock_contention *con, struct lock_stat *s fprintf(lock_output, "%llx%s %s%s %s\n", (unsigned long long)st->addr, sep, st->name, sep, get_type_name(st->flags)); break; + case LOCK_AGGR_CGROUP: + fprintf(lock_output, "%s\n",st->name); + break; default: break; } @@ -1999,6 +2033,27 @@ static int check_lock_contention_options(const struct option *options, return -1; } + if (show_lock_cgroups && !use_bpf) { + pr_err("Cgroups are available only with BPF\n"); + parse_options_usage(usage, options, "lock-cgroup", 0); + parse_options_usage(NULL, options, "use-bpf", 0); + return -1; + } + + if (show_lock_cgroups && show_lock_addrs) { + pr_err("Cannot use cgroup and addr mode together\n"); + parse_options_usage(usage, options, "lock-cgroup", 0); + parse_options_usage(NULL, options, "lock-addr", 0); + return -1; + } + + if (show_lock_cgroups && show_thread_stats) { + pr_err("Cannot use cgroup and thread mode together\n"); + parse_options_usage(usage, options, "lock-cgroup", 0); + parse_options_usage(NULL, options, "threads", 0); + return -1; + } + if (symbol_conf.field_sep) { if (strstr(symbol_conf.field_sep, ":") || /* part of type flags */ strstr(symbol_conf.field_sep, "+") || /* part of caller offset */ @@ -2040,6 +2095,7 @@ static int __cmd_contention(int argc, const char **argv) .filters = &filters, .save_callstack = needs_callstack(), .owner = show_lock_owner, + .cgroups = RB_ROOT, }; lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table)); @@ -2059,7 +2115,8 @@ static int __cmd_contention(int argc, const char **argv) con.machine = &session->machines.host; con.aggr_mode = aggr_mode = show_thread_stats ? LOCK_AGGR_TASK : - show_lock_addrs ? LOCK_AGGR_ADDR : LOCK_AGGR_CALLER; + show_lock_addrs ? LOCK_AGGR_ADDR : + show_lock_cgroups ? LOCK_AGGR_CGROUP : LOCK_AGGR_CALLER; if (con.aggr_mode == LOCK_AGGR_CALLER) con.save_callstack = true; @@ -2158,7 +2215,7 @@ static int __cmd_contention(int argc, const char **argv) out_delete: lock_filter_finish(); evlist__delete(con.evlist); - lock_contention_finish(); + lock_contention_finish(&con); perf_session__delete(session); zfree(&lockhash_table); return err; @@ -2421,6 +2478,7 @@ static int parse_call_stack(const struct option *opt __maybe_unused, const char entry = malloc(sizeof(*entry) + strlen(tok) + 1); if (entry == NULL) { pr_err("Memory allocation failure\n"); + free(s); return -1; } @@ -2450,6 +2508,56 @@ static int parse_output(const struct option *opt __maybe_unused, const char *str return 0; } +static bool add_lock_cgroup(char *name) +{ + u64 *tmp; + struct cgroup *cgrp; + + cgrp = cgroup__new(name, /*do_open=*/false); + if (cgrp == NULL) { + pr_err("Failed to create cgroup: %s\n", name); + return false; + } + + if (read_cgroup_id(cgrp) < 0) { + pr_err("Failed to read cgroup id for %s\n", name); + cgroup__put(cgrp); + return false; + } + + tmp = realloc(filters.cgrps, (filters.nr_cgrps + 1) * sizeof(*filters.cgrps)); + if (tmp == NULL) { + pr_err("Memory allocation failure\n"); + return false; + } + + tmp[filters.nr_cgrps++] = cgrp->id; + filters.cgrps = tmp; + cgroup__put(cgrp); + return true; +} + +static int parse_cgroup_filter(const struct option *opt __maybe_unused, const char *str, + int unset __maybe_unused) +{ + char *s, *tmp, *tok; + int ret = 0; + + s = strdup(str); + if (s == NULL) + return -1; + + for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { + if (!add_lock_cgroup(tok)) { + ret = -1; + break; + } + } + + free(s); + return ret; +} + int cmd_lock(int argc, const char **argv) { const struct option lock_options[] = { @@ -2523,6 +2631,9 @@ int cmd_lock(int argc, const char **argv) OPT_BOOLEAN('o', "lock-owner", &show_lock_owner, "show lock owners instead of waiters"), OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep, "separator", "print result in CSV format with custom separator"), + OPT_BOOLEAN(0, "lock-cgroup", &show_lock_cgroups, "show lock stats by cgroup"), + OPT_CALLBACK('G', "cgroup-filter", NULL, "CGROUPS", + "Filter specific cgroups", parse_cgroup_filter), OPT_PARENT(lock_options) }; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 34bb31f08bb5..dcf288a4fb9a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -906,6 +906,65 @@ static int record__config_off_cpu(struct record *rec) return off_cpu_prepare(rec->evlist, &rec->opts.target, &rec->opts); } +static bool record__tracking_system_wide(struct record *rec) +{ + struct evlist *evlist = rec->evlist; + struct evsel *evsel; + + /* + * If non-dummy evsel exists, system_wide sideband is need to + * help parse sample information. + * For example, PERF_EVENT_MMAP event to help parse symbol, + * and PERF_EVENT_COMM event to help parse task executable name. + */ + evlist__for_each_entry(evlist, evsel) { + if (!evsel__is_dummy_event(evsel)) + return true; + } + + return false; +} + +static int record__config_tracking_events(struct record *rec) +{ + struct record_opts *opts = &rec->opts; + struct evlist *evlist = rec->evlist; + bool system_wide = false; + struct evsel *evsel; + + /* + * For initial_delay, system wide or a hybrid system, we need to add + * tracking event so that we can track PERF_RECORD_MMAP to cover the + * delay of waiting or event synthesis. + */ + if (opts->target.initial_delay || target__has_cpu(&opts->target) || + perf_pmus__num_core_pmus() > 1) { + + /* + * User space tasks can migrate between CPUs, so when tracing + * selected CPUs, sideband for all CPUs is still needed. + */ + if (!!opts->target.cpu_list && record__tracking_system_wide(rec)) + system_wide = true; + + evsel = evlist__findnew_tracking_event(evlist, system_wide); + if (!evsel) + return -ENOMEM; + + /* + * Enable the tracking event when the process is forked for + * initial_delay, immediately for system wide. + */ + if (opts->target.initial_delay && !evsel->immediate && + !target__has_cpu(&opts->target)) + evsel->core.attr.enable_on_exec = 1; + else + evsel->immediate = 1; + } + + return 0; +} + static bool record__kcore_readable(struct machine *machine) { char kcore[PATH_MAX]; @@ -1286,33 +1345,6 @@ static int record__open(struct record *rec) struct record_opts *opts = &rec->opts; int rc = 0; - /* - * For initial_delay, system wide or a hybrid system, we need to add a - * dummy event so that we can track PERF_RECORD_MMAP to cover the delay - * of waiting or event synthesis. - */ - if (opts->target.initial_delay || target__has_cpu(&opts->target) || - perf_pmus__num_core_pmus() > 1) { - pos = evlist__get_tracking_event(evlist); - if (!evsel__is_dummy_event(pos)) { - /* Set up dummy event. */ - if (evlist__add_dummy(evlist)) - return -ENOMEM; - pos = evlist__last(evlist); - evlist__set_tracking_event(evlist, pos); - } - - /* - * Enable the dummy event when the process is forked for - * initial_delay, immediately for system wide. - */ - if (opts->target.initial_delay && !pos->immediate && - !target__has_cpu(&opts->target)) - pos->core.attr.enable_on_exec = 1; - else - pos->immediate = 1; - } - evlist__config(evlist, opts, &callchain_param); evlist__for_each_entry(evlist, pos) { @@ -4195,6 +4227,12 @@ int cmd_record(int argc, const char **argv) goto out; } + err = record__config_tracking_events(rec); + if (err) { + pr_err("record__config_tracking_events failed, error %d\n", err); + goto out; + } + err = record__init_thread_masks(rec); if (err) { pr_err("Failed to initialize parallel data streaming masks\n"); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index dcedfe00f04d..9cb1da2dc0c0 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -691,10 +691,25 @@ static int report__browse_hists(struct report *rep) static int report__collapse_hists(struct report *rep) { + struct perf_session *session = rep->session; + struct evlist *evlist = session->evlist; struct ui_progress prog; struct evsel *pos; int ret = 0; + /* + * The pipe data needs to setup hierarchy hpp formats now, because it + * cannot know about evsels in the data before reading the data. The + * normal file data saves the event (attribute) info in the header + * section, but pipe does not have the luxury. + */ + if (perf_data__is_pipe(session->data)) { + if (perf_hpp__setup_hists_formats(&perf_hpp_list, evlist) < 0) { + ui__error("Failed to setup hierarchy output formats\n"); + return -1; + } + } + ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); evlist__for_each_entry(rep->session->evlist, pos) { diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9ab300b6f131..dd6065afbbaf 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1385,7 +1385,7 @@ static int pid_cmp(struct work_atoms *l, struct work_atoms *r) { pid_t l_tid, r_tid; - if (RC_CHK_ACCESS(l->thread) == RC_CHK_ACCESS(r->thread)) + if (RC_CHK_EQUAL(l->thread, r->thread)) return 0; l_tid = thread__tid(l->thread); r_tid = thread__tid(r->thread); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 517bf25750c8..b1f57401ff23 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -3899,7 +3899,7 @@ int cmd_script(int argc, const char **argv) "comma separated output fields prepend with 'type:'. " "+field to add and -field to remove." "Valid types: hw,sw,trace,raw,synth. " - "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,dsoff" + "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,dsoff," "addr,symoff,srcline,period,iregs,uregs,brstack," "brstacksym,flags,data_src,weight,bpf-output,brstackinsn," "brstackinsnlen,brstackoff,callindent,insn,insnlen,synth," diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 07b48f6df48e..a3af805a1d57 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1622,7 +1622,7 @@ static int perf_stat_init_aggr_mode(void) * taking the highest cpu number to be the size of * the aggregation translate cpumap. */ - if (evsel_list->core.user_requested_cpus) + if (!perf_cpu_map__empty(evsel_list->core.user_requested_cpus)) nr = perf_cpu_map__max(evsel_list->core.user_requested_cpus).cpu; else nr = 0; diff --git a/tools/perf/builtin-version.c b/tools/perf/builtin-version.c index e5859c70e195..ac20c2b9bbc2 100644 --- a/tools/perf/builtin-version.c +++ b/tools/perf/builtin-version.c @@ -81,6 +81,7 @@ static void library_status(void) STATUS(HAVE_ZSTD_SUPPORT, zstd); STATUS(HAVE_LIBPFM, libpfm4); STATUS(HAVE_LIBTRACEEVENT, libtraceevent); + STATUS(HAVE_BPF_SKEL, bpf_skeletons); } int cmd_version(int argc, const char **argv) diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index e21caadda7c1..66ba33dbcef2 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh @@ -162,6 +162,7 @@ check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include " -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"' check arch/x86/include/asm/amd-ibs.h '-I "^#include [<\"]\(asm/\)*msr-index.h"' check arch/arm64/include/asm/cputype.h '-I "^#include [<\"]\(asm/\)*sysreg.h"' +check include/asm-generic/unaligned.h '-I "^#include " -I "^#include " -I "^#pragma GCC diagnostic"' check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"' check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"' check include/linux/build_bug.h '-I "^#\(ifndef\|endif\)\( \/\/\)* static_assert$"' diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh index 978249d7868c..f224d79b89e6 100644 --- a/tools/perf/perf-completion.sh +++ b/tools/perf/perf-completion.sh @@ -164,7 +164,7 @@ __perf_main () $prev_skip_opts == @(record|stat|top) ]]; then local cur1=${COMP_WORDS[COMP_CWORD]} - local raw_evts=$($cmd list --raw-dump) + local raw_evts=$($cmd list --raw-dump hw sw cache tracepoint pmu sdt) local arr s tmp result cpu_evts # aarch64 doesn't have /sys/bus/event_source/devices/cpu/events @@ -198,6 +198,14 @@ __perf_main () else __perfcomp_colon "$evts" "$cur1" fi + elif [[ $prev == @("--pfm-events") && + $prev_skip_opts == @(record|stat|top) ]]; then + local evts=$($cmd list --raw-dump pfm) + __perfcomp "$evts" "$cur" + elif [[ $prev == @("-M"|"--metrics") && + $prev_skip_opts == @(stat) ]]; then + local metrics=$($cmd list --raw-dump metric metricgroup) + __perfcomp "$metrics" "$cur" else # List subcommands for perf commands if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched| diff --git a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/metrics.json b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/metrics.json index 1e7e8901a445..e2848a9d4848 100644 --- a/tools/perf/pmu-events/arch/arm64/ampere/ampereone/metrics.json +++ b/tools/perf/pmu-events/arch/arm64/ampere/ampereone/metrics.json @@ -1,362 +1,384 @@ [ { + "MetricName": "branch_miss_pred_rate", "MetricExpr": "BR_MIS_PRED / BR_PRED", "BriefDescription": "Branch predictor misprediction rate. May not count branches that are never resolved because they are in the misprediction shadow of an earlier branch", - "MetricGroup": "Branch Prediction", - "MetricName": "Misprediction" + "MetricGroup": "branch", + "ScaleUnit": "100%" }, { - "MetricExpr": "BR_MIS_PRED_RETIRED / BR_RETIRED", - "BriefDescription": "Branch predictor misprediction rate", - "MetricGroup": "Branch Prediction", - "MetricName": "Misprediction (retired)" - }, - { - "MetricExpr": "BUS_ACCESS / ( BUS_CYCLES * 1)", + "MetricName": "bus_utilization", + "MetricExpr": "((BUS_ACCESS / (BUS_CYCLES * 1)) * 100)", "BriefDescription": "Core-to-uncore bus utilization", "MetricGroup": "Bus", - "MetricName": "Bus utilization" + "ScaleUnit": "1percent of bus cycles" }, { - "MetricExpr": "L1D_CACHE_REFILL / L1D_CACHE", - "BriefDescription": "L1D cache miss rate", - "MetricGroup": "Cache", - "MetricName": "L1D cache miss" + "MetricName": "l1d_cache_miss_ratio", + "MetricExpr": "(L1D_CACHE_REFILL / L1D_CACHE)", + "BriefDescription": "This metric measures the ratio of level 1 data cache accesses missed to the total number of level 1 data cache accesses. This gives an indication of the effectiveness of the level 1 data cache.", + "MetricGroup": "Miss_Ratio;L1D_Cache_Effectiveness", + "ScaleUnit": "1per cache access" }, { + "MetricName": "l1i_cache_miss_ratio", + "MetricExpr": "(L1I_CACHE_REFILL / L1I_CACHE)", + "BriefDescription": "This metric measures the ratio of level 1 instruction cache accesses missed to the total number of level 1 instruction cache accesses. This gives an indication of the effectiveness of the level 1 instruction cache.", + "MetricGroup": "Miss_Ratio;L1I_Cache_Effectiveness", + "ScaleUnit": "1per cache access" + }, + { + "MetricName": "Miss_Ratio;l1d_cache_read_miss", "MetricExpr": "L1D_CACHE_LMISS_RD / L1D_CACHE_RD", "BriefDescription": "L1D cache read miss rate", "MetricGroup": "Cache", - "MetricName": "L1D cache read miss" + "ScaleUnit": "1per cache read access" }, { - "MetricExpr": "L1I_CACHE_REFILL / L1I_CACHE", - "BriefDescription": "L1I cache miss rate", - "MetricGroup": "Cache", - "MetricName": "L1I cache miss" - }, - { - "MetricExpr": "L2D_CACHE_REFILL / L2D_CACHE", - "BriefDescription": "L2 cache miss rate", - "MetricGroup": "Cache", - "MetricName": "L2 cache miss" + "MetricName": "l2_cache_miss_ratio", + "MetricExpr": "(L2D_CACHE_REFILL / L2D_CACHE)", + "BriefDescription": "This metric measures the ratio of level 2 cache accesses missed to the total number of level 2 cache accesses. This gives an indication of the effectiveness of the level 2 cache, which is a unified cache that stores both data and instruction. Note that cache accesses in this cache are either data memory access or instruction fetch as this is a unified cache.", + "MetricGroup": "Miss_Ratio;L2_Cache_Effectiveness", + "ScaleUnit": "1per cache access" }, { + "MetricName": "l1i_cache_read_miss_rate", "MetricExpr": "L1I_CACHE_LMISS / L1I_CACHE", "BriefDescription": "L1I cache read miss rate", "MetricGroup": "Cache", - "MetricName": "L1I cache read miss" + "ScaleUnit": "1per cache access" }, { + "MetricName": "l2d_cache_read_miss_rate", "MetricExpr": "L2D_CACHE_LMISS_RD / L2D_CACHE_RD", "BriefDescription": "L2 cache read miss rate", "MetricGroup": "Cache", - "MetricName": "L2 cache read miss" + "ScaleUnit": "1per cache read access" }, { - "MetricExpr": "(L1D_CACHE_LMISS_RD * 1000) / INST_RETIRED", + "MetricName": "l1d_cache_miss_mpki", + "MetricExpr": "(L1D_CACHE_LMISS_RD * 1e3) / INST_RETIRED", "BriefDescription": "Misses per thousand instructions (data)", "MetricGroup": "Cache", - "MetricName": "MPKI data" + "ScaleUnit": "1MPKI" }, { - "MetricExpr": "(L1I_CACHE_LMISS * 1000) / INST_RETIRED", + "MetricName": "l1i_cache_miss_mpki", + "MetricExpr": "(L1I_CACHE_LMISS * 1e3) / INST_RETIRED", "BriefDescription": "Misses per thousand instructions (instruction)", "MetricGroup": "Cache", - "MetricName": "MPKI instruction" + "ScaleUnit": "1MPKI" }, { - "MetricExpr": "ASE_SPEC / OP_SPEC", - "BriefDescription": "Proportion of advanced SIMD data processing operations (excluding DP_SPEC/LD_SPEC) operations", - "MetricGroup": "Instruction", - "MetricName": "ASE mix" + "MetricName": "simd_percentage", + "MetricExpr": "((ASE_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures advanced SIMD operations as a percentage of total operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "CRYPTO_SPEC / OP_SPEC", - "BriefDescription": "Proportion of crypto data processing operations", - "MetricGroup": "Instruction", - "MetricName": "Crypto mix" + "MetricName": "crypto_percentage", + "MetricExpr": "((CRYPTO_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures crypto operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "VFP_SPEC / (duration_time *1000000000)", + "MetricName": "gflops", + "MetricExpr": "VFP_SPEC / (duration_time * 1e9)", "BriefDescription": "Giga-floating point operations per second", - "MetricGroup": "Instruction", - "MetricName": "GFLOPS_ISSUED" + "MetricGroup": "InstructionMix" }, { - "MetricExpr": "DP_SPEC / OP_SPEC", - "BriefDescription": "Proportion of integer data processing operations", - "MetricGroup": "Instruction", - "MetricName": "Integer mix" + "MetricName": "integer_dp_percentage", + "MetricExpr": "((DP_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures scalar integer operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "INST_RETIRED / CPU_CYCLES", - "BriefDescription": "Instructions per cycle", - "MetricGroup": "Instruction", - "MetricName": "IPC" + "MetricName": "ipc", + "MetricExpr": "(INST_RETIRED / CPU_CYCLES)", + "BriefDescription": "This metric measures the number of instructions retired per cycle.", + "MetricGroup": "General", + "ScaleUnit": "1per cycle" }, { - "MetricExpr": "LD_SPEC / OP_SPEC", - "BriefDescription": "Proportion of load operations", - "MetricGroup": "Instruction", - "MetricName": "Load mix" + "MetricName": "load_percentage", + "MetricExpr": "((LD_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures load operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "LDST_SPEC/ OP_SPEC", - "BriefDescription": "Proportion of load & store operations", - "MetricGroup": "Instruction", - "MetricName": "Load-store mix" + "MetricName": "load_store_spec_rate", + "MetricExpr": "((LDST_SPEC / INST_SPEC) * 100)", + "BriefDescription": "The rate of load or store instructions speculatively executed to overall instructions speclatively executed", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "INST_RETIRED / (duration_time * 1000000)", + "MetricName": "retired_mips", + "MetricExpr": "INST_RETIRED / (duration_time * 1e6)", "BriefDescription": "Millions of instructions per second", - "MetricGroup": "Instruction", - "MetricName": "MIPS_RETIRED" + "MetricGroup": "InstructionMix" }, { - "MetricExpr": "INST_SPEC / (duration_time * 1000000)", + "MetricName": "spec_utilization_mips", + "MetricExpr": "INST_SPEC / (duration_time * 1e6)", "BriefDescription": "Millions of instructions per second", - "MetricGroup": "Instruction", - "MetricName": "MIPS_UTILIZATION" + "MetricGroup": "PEutilization" }, { - "MetricExpr": "PC_WRITE_SPEC / OP_SPEC", - "BriefDescription": "Proportion of software change of PC operations", - "MetricGroup": "Instruction", - "MetricName": "PC write mix" + "MetricName": "pc_write_spec_rate", + "MetricExpr": "((PC_WRITE_SPEC / INST_SPEC) * 100)", + "BriefDescription": "The rate of software change of the PC speculatively executed to overall instructions speclatively executed", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "ST_SPEC / OP_SPEC", - "BriefDescription": "Proportion of store operations", - "MetricGroup": "Instruction", - "MetricName": "Store mix" + "MetricName": "store_percentage", + "MetricExpr": "((ST_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures store operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "VFP_SPEC / OP_SPEC", - "BriefDescription": "Proportion of FP operations", - "MetricGroup": "Instruction", - "MetricName": "VFP mix" + "MetricName": "scalar_fp_percentage", + "MetricExpr": "((VFP_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures scalar floating point operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" }, { - "MetricExpr": "1 - (OP_RETIRED/ (CPU_CYCLES * 4))", - "BriefDescription": "Proportion of slots lost", - "MetricGroup": "Speculation / TDA", - "MetricName": "CPU lost" + "MetricName": "retired_rate", + "MetricExpr": "OP_RETIRED / OP_SPEC", + "BriefDescription": "Of all the micro-operations issued, what percentage are retired(committed)", + "MetricGroup": "General", + "ScaleUnit": "100%" }, { - "MetricExpr": "OP_RETIRED/ (CPU_CYCLES * 4)", - "BriefDescription": "Proportion of slots retiring", - "MetricGroup": "Speculation / TDA", - "MetricName": "CPU utilization" + "MetricName": "wasted", + "MetricExpr": "1 - (OP_RETIRED / (CPU_CYCLES * #slots))", + "BriefDescription": "Of all the micro-operations issued, what proportion are lost", + "MetricGroup": "General", + "ScaleUnit": "100%" }, { - "MetricExpr": "OP_RETIRED - OP_SPEC", - "BriefDescription": "Operations lost due to misspeculation", - "MetricGroup": "Speculation / TDA", - "MetricName": "Operations lost" + "MetricName": "wasted_rate", + "MetricExpr": "1 - OP_RETIRED / OP_SPEC", + "BriefDescription": "Of all the micro-operations issued, what percentage are not retired(committed)", + "MetricGroup": "General", + "ScaleUnit": "100%" }, { - "MetricExpr": "1 - (OP_RETIRED / OP_SPEC)", - "BriefDescription": "Proportion of operations lost", - "MetricGroup": "Speculation / TDA", - "MetricName": "Operations lost (ratio)" - }, - { - "MetricExpr": "OP_RETIRED / OP_SPEC", - "BriefDescription": "Proportion of operations retired", - "MetricGroup": "Speculation / TDA", - "MetricName": "Operations retired" - }, - { - "MetricExpr": "STALL_BACKEND_CACHE / CPU_CYCLES", + "MetricName": "stall_backend_cache_rate", + "MetricExpr": "((STALL_BACKEND_CACHE / CPU_CYCLES) * 100)", "BriefDescription": "Proportion of cycles stalled and no operations issued to backend and cache miss", "MetricGroup": "Stall", - "MetricName": "Stall backend cache cycles" + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "STALL_BACKEND_RESOURCE / CPU_CYCLES", + "MetricName": "stall_backend_resource_rate", + "MetricExpr": "((STALL_BACKEND_RESOURCE / CPU_CYCLES) * 100)", "BriefDescription": "Proportion of cycles stalled and no operations issued to backend and resource full", "MetricGroup": "Stall", - "MetricName": "Stall backend resource cycles" + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "STALL_BACKEND_TLB / CPU_CYCLES", + "MetricName": "stall_backend_tlb_rate", + "MetricExpr": "((STALL_BACKEND_TLB / CPU_CYCLES) * 100)", "BriefDescription": "Proportion of cycles stalled and no operations issued to backend and TLB miss", "MetricGroup": "Stall", - "MetricName": "Stall backend tlb cycles" + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "STALL_FRONTEND_CACHE / CPU_CYCLES", + "MetricName": "stall_frontend_cache_rate", + "MetricExpr": "((STALL_FRONTEND_CACHE / CPU_CYCLES) * 100)", "BriefDescription": "Proportion of cycles stalled and no ops delivered from frontend and cache miss", "MetricGroup": "Stall", - "MetricName": "Stall frontend cache cycles" + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "STALL_FRONTEND_TLB / CPU_CYCLES", + "MetricName": "stall_frontend_tlb_rate", + "MetricExpr": "((STALL_FRONTEND_TLB / CPU_CYCLES) * 100)", "BriefDescription": "Proportion of cycles stalled and no ops delivered from frontend and TLB miss", "MetricGroup": "Stall", - "MetricName": "Stall frontend tlb cycles" + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "DTLB_WALK / L1D_TLB", - "BriefDescription": "D-side walk per d-side translation request", - "MetricGroup": "TLB", - "MetricName": "DTLB walks" + "MetricName": "dtlb_walk_ratio", + "MetricExpr": "(DTLB_WALK / L1D_TLB)", + "BriefDescription": "This metric measures the ratio of data TLB Walks to the total number of data TLB accesses. This gives an indication of the effectiveness of the data TLB accesses.", + "MetricGroup": "Miss_Ratio;DTLB_Effectiveness", + "ScaleUnit": "1per TLB access" }, { - "MetricExpr": "ITLB_WALK / L1I_TLB", - "BriefDescription": "I-side walk per i-side translation request", - "MetricGroup": "TLB", - "MetricName": "ITLB walks" + "MetricName": "itlb_walk_ratio", + "MetricExpr": "(ITLB_WALK / L1I_TLB)", + "BriefDescription": "This metric measures the ratio of instruction TLB Walks to the total number of instruction TLB accesses. This gives an indication of the effectiveness of the instruction TLB accesses.", + "MetricGroup": "Miss_Ratio;ITLB_Effectiveness", + "ScaleUnit": "1per TLB access" }, { - "MetricExpr": "STALL_SLOT_BACKEND / (CPU_CYCLES * 4)", - "BriefDescription": "Fraction of slots backend bound", - "MetricGroup": "TopDownL1", - "MetricName": "backend" + "ArchStdEvent": "backend_bound" }, { - "MetricExpr": "1 - (retiring + lost + backend)", - "BriefDescription": "Fraction of slots frontend bound", - "MetricGroup": "TopDownL1", - "MetricName": "frontend" + "ArchStdEvent": "frontend_bound", + "MetricExpr": "100 - (retired_fraction + slots_lost_misspeculation_fraction + backend_bound)" }, { - "MetricExpr": "((OP_SPEC - OP_RETIRED) / (CPU_CYCLES * 4))", + "MetricName": "slots_lost_misspeculation_fraction", + "MetricExpr": "100 * ((OP_SPEC - OP_RETIRED) / (CPU_CYCLES * #slots))", "BriefDescription": "Fraction of slots lost due to misspeculation", - "MetricGroup": "TopDownL1", - "MetricName": "lost" + "MetricGroup": "Default;TopdownL1", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "(OP_RETIRED / (CPU_CYCLES * 4))", + "MetricName": "retired_fraction", + "MetricExpr": "100 * (OP_RETIRED / (CPU_CYCLES * #slots))", "BriefDescription": "Fraction of slots retiring, useful work", - "MetricGroup": "TopDownL1", - "MetricName": "retiring" + "MetricGroup": "Default;TopdownL1", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "backend - backend_memory", + "MetricName": "backend_core", + "MetricExpr": "(backend_bound / 100) - backend_memory", "BriefDescription": "Fraction of slots the CPU was stalled due to backend non-memory subsystem issues", - "MetricGroup": "TopDownL2", - "MetricName": "backend_core" + "MetricGroup": "TopdownL2", + "ScaleUnit": "100%" }, { - "MetricExpr": "(STALL_BACKEND_TLB + STALL_BACKEND_CACHE + STALL_BACKEND_MEM) / CPU_CYCLES ", + "MetricName": "backend_memory", + "MetricExpr": "(STALL_BACKEND_TLB + STALL_BACKEND_CACHE) / CPU_CYCLES", "BriefDescription": "Fraction of slots the CPU was stalled due to backend memory subsystem issues (cache/tlb miss)", - "MetricGroup": "TopDownL2", - "MetricName": "backend_memory" + "MetricGroup": "TopdownL2", + "ScaleUnit": "100%" }, { - "MetricExpr": " (BR_MIS_PRED_RETIRED / GPC_FLUSH) * lost", + "MetricName": "branch_mispredict", + "MetricExpr": "(BR_MIS_PRED_RETIRED / GPC_FLUSH) * slots_lost_misspeculation_fraction", "BriefDescription": "Fraction of slots lost due to branch misprediciton", - "MetricGroup": "TopDownL2", - "MetricName": "branch_mispredict" + "MetricGroup": "TopdownL2", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "frontend - frontend_latency", + "MetricName": "frontend_bandwidth", + "MetricExpr": "frontend_bound - frontend_latency", "BriefDescription": "Fraction of slots the CPU did not dispatch at full bandwidth - able to dispatch partial slots only (1, 2, or 3 uops)", - "MetricGroup": "TopDownL2", - "MetricName": "frontend_bandwidth" + "MetricGroup": "TopdownL2", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "(STALL_FRONTEND - ((STALL_SLOT_FRONTEND - (frontend * CPU_CYCLES * 4)) / 4)) / CPU_CYCLES", + "MetricName": "frontend_latency", + "MetricExpr": "((STALL_FRONTEND - ((STALL_SLOT_FRONTEND - ((frontend_bound / 100) * CPU_CYCLES * #slots)) / #slots)) / CPU_CYCLES) * 100", "BriefDescription": "Fraction of slots the CPU was stalled due to frontend latency issues (cache/tlb miss); nothing to dispatch", - "MetricGroup": "TopDownL2", - "MetricName": "frontend_latency" + "MetricGroup": "TopdownL2", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "lost - branch_mispredict", + "MetricName": "other_miss_pred", + "MetricExpr": "slots_lost_misspeculation_fraction - branch_mispredict", "BriefDescription": "Fraction of slots lost due to other/non-branch misprediction misspeculation", - "MetricGroup": "TopDownL2", - "MetricName": "other_clears" + "MetricGroup": "TopdownL2", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "(IXU_NUM_UOPS_ISSUED + FSU_ISSUED) / (CPU_CYCLES * 6)", + "MetricName": "pipe_utilization", + "MetricExpr": "100 * ((IXU_NUM_UOPS_ISSUED + FSU_ISSUED) / (CPU_CYCLES * 6))", "BriefDescription": "Fraction of execute slots utilized", - "MetricGroup": "TopDownL2", - "MetricName": "pipe_utilization" + "MetricGroup": "TopdownL2", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "STALL_BACKEND_MEM / CPU_CYCLES", + "MetricName": "d_cache_l2_miss_rate", + "MetricExpr": "((STALL_BACKEND_MEM / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled due to data L2 cache miss", - "MetricGroup": "TopDownL3", - "MetricName": "d_cache_l2_miss" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "STALL_BACKEND_CACHE / CPU_CYCLES", + "MetricName": "d_cache_miss_rate", + "MetricExpr": "((STALL_BACKEND_CACHE / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled due to data cache miss", - "MetricGroup": "TopDownL3", - "MetricName": "d_cache_miss" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "STALL_BACKEND_TLB / CPU_CYCLES", + "MetricName": "d_tlb_miss_rate", + "MetricExpr": "((STALL_BACKEND_TLB / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled due to data TLB miss", - "MetricGroup": "TopDownL3", - "MetricName": "d_tlb_miss" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "FSU_ISSUED / (CPU_CYCLES * 2)", + "MetricName": "fsu_pipe_utilization", + "MetricExpr": "((FSU_ISSUED / (CPU_CYCLES * 2)) * 100)", "BriefDescription": "Fraction of FSU execute slots utilized", - "MetricGroup": "TopDownL3", - "MetricName": "fsu_pipe_utilization" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "STALL_FRONTEND_CACHE / CPU_CYCLES", + "MetricName": "i_cache_miss_rate", + "MetricExpr": "((STALL_FRONTEND_CACHE / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled due to instruction cache miss", - "MetricGroup": "TopDownL3", - "MetricName": "i_cache_miss" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": " STALL_FRONTEND_TLB / CPU_CYCLES ", + "MetricName": "i_tlb_miss_rate", + "MetricExpr": "((STALL_FRONTEND_TLB / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled due to instruction TLB miss", - "MetricGroup": "TopDownL3", - "MetricName": "i_tlb_miss" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "IXU_NUM_UOPS_ISSUED / (CPU_CYCLES / 4)", + "MetricName": "ixu_pipe_utilization", + "MetricExpr": "((IXU_NUM_UOPS_ISSUED / (CPU_CYCLES * #slots)) * 100)", "BriefDescription": "Fraction of IXU execute slots utilized", - "MetricGroup": "TopDownL3", - "MetricName": "ixu_pipe_utilization" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "IDR_STALL_FLUSH / CPU_CYCLES", + "MetricName": "stall_recovery_rate", + "MetricExpr": "((IDR_STALL_FLUSH / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled due to flush recovery", - "MetricGroup": "TopDownL3", - "MetricName": "recovery" + "MetricGroup": "TopdownL3", + "ScaleUnit": "1percent of slots" }, { - "MetricExpr": "STALL_BACKEND_RESOURCE / CPU_CYCLES", - "BriefDescription": "Fraction of cycles the CPU was stalled due to core resource shortage", - "MetricGroup": "TopDownL3", - "MetricName": "resource" - }, - { - "MetricExpr": "IDR_STALL_FSU_SCHED / CPU_CYCLES ", + "MetricName": "stall_fsu_sched_rate", + "MetricExpr": "((IDR_STALL_FSU_SCHED / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled and FSU was full", - "MetricGroup": "TopDownL4", - "MetricName": "stall_fsu_sched" + "MetricGroup": "TopdownL4", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "IDR_STALL_IXU_SCHED / CPU_CYCLES ", + "MetricName": "stall_ixu_sched_rate", + "MetricExpr": "((IDR_STALL_IXU_SCHED / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled and IXU was full", - "MetricGroup": "TopDownL4", - "MetricName": "stall_ixu_sched" + "MetricGroup": "TopdownL4", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "IDR_STALL_LOB_ID / CPU_CYCLES ", + "MetricName": "stall_lob_id_rate", + "MetricExpr": "((IDR_STALL_LOB_ID / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled and LOB was full", - "MetricGroup": "TopDownL4", - "MetricName": "stall_lob_id" + "MetricGroup": "TopdownL4", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "IDR_STALL_ROB_ID / CPU_CYCLES", + "MetricName": "stall_rob_id_rate", + "MetricExpr": "((IDR_STALL_ROB_ID / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled and ROB was full", - "MetricGroup": "TopDownL4", - "MetricName": "stall_rob_id" + "MetricGroup": "TopdownL4", + "ScaleUnit": "1percent of cycles" }, { - "MetricExpr": "IDR_STALL_SOB_ID / CPU_CYCLES ", + "MetricName": "stall_sob_id_rate", + "MetricExpr": "((IDR_STALL_SOB_ID / CPU_CYCLES) * 100)", "BriefDescription": "Fraction of cycles the CPU was stalled and SOB was full", - "MetricGroup": "TopDownL4", - "MetricName": "stall_sob_id" + "MetricGroup": "TopdownL4", + "ScaleUnit": "1percent of cycles" } ] diff --git a/tools/perf/pmu-events/arch/arm64/arm/cmn/sys/cmn.json b/tools/perf/pmu-events/arch/arm64/arm/cmn/sys/cmn.json new file mode 100644 index 000000000000..428605c37d10 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/cmn/sys/cmn.json @@ -0,0 +1,266 @@ +[ + { + "EventName": "hnf_cache_miss", + "EventidCode": "0x1", + "NodeType": "0x5", + "BriefDescription": "Counts total cache misses in first lookup result (high priority).", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_slc_sf_cache_access", + "EventidCode": "0x2", + "NodeType": "0x5", + "BriefDescription": "Counts number of cache accesses in first access (high priority).", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_cache_fill", + "EventidCode": "0x3", + "NodeType": "0x5", + "BriefDescription": "Counts total allocations in HN SLC (all cache line allocations to SLC).", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_pocq_retry", + "EventidCode": "0x4", + "NodeType": "0x5", + "BriefDescription": "Counts number of retried requests.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_pocq_reqs_recvd", + "EventidCode": "0x5", + "NodeType": "0x5", + "BriefDescription": "Counts number of requests that HN receives.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_sf_hit", + "EventidCode": "0x6", + "NodeType": "0x5", + "BriefDescription": "Counts number of SF hits.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_sf_evictions", + "EventidCode": "0x7", + "NodeType": "0x5", + "BriefDescription": "Counts number of SF eviction cache invalidations initiated.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_dir_snoops_sent", + "EventidCode": "0x8", + "NodeType": "0x5", + "BriefDescription": "Counts number of directed snoops sent (not including SF back invalidation).", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_brd_snoops_sent", + "EventidCode": "0x9", + "NodeType": "0x5", + "BriefDescription": "Counts number of multicast snoops sent (not including SF back invalidation).", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_slc_eviction", + "EventidCode": "0xa", + "NodeType": "0x5", + "BriefDescription": "Counts number of SLC evictions (dirty only).", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_slc_fill_invalid_way", + "EventidCode": "0xb", + "NodeType": "0x5", + "BriefDescription": "Counts number of SLC fills to an invalid way.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_mc_retries", + "EventidCode": "0xc", + "NodeType": "0x5", + "BriefDescription": "Counts number of retried transactions by the MC.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_mc_reqs", + "EventidCode": "0xd", + "NodeType": "0x5", + "BriefDescription": "Counts number of requests that are sent to MC.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hnf_qos_hh_retry", + "EventidCode": "0xe", + "NodeType": "0x5", + "BriefDescription": "Counts number of times a HighHigh priority request is protocolretried at the HN‑F.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_s0_rdata_beats", + "EventidCode": "0x1", + "NodeType": "0xa", + "BriefDescription": "Number of RData beats (RVALID and RREADY) dispatched on port 0. This event measures the read bandwidth, including CMO responses.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_s1_rdata_beats", + "EventidCode": "0x2", + "NodeType": "0xa", + "BriefDescription": "Number of RData beats (RVALID and RREADY) dispatched on port 1. This event measures the read bandwidth, including CMO responses.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_s2_rdata_beats", + "EventidCode": "0x3", + "NodeType": "0xa", + "BriefDescription": "Number of RData beats (RVALID and RREADY) dispatched on port 2. This event measures the read bandwidth, including CMO responses.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_rxdat_flits", + "EventidCode": "0x4", + "NodeType": "0xa", + "BriefDescription": "Number of RXDAT flits received. This event measures the true read data bandwidth, excluding CMOs.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_txdat_flits", + "EventidCode": "0x5", + "NodeType": "0xa", + "BriefDescription": "Number of TXDAT flits dispatched. This event measures the write bandwidth.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_txreq_flits_total", + "EventidCode": "0x6", + "NodeType": "0xa", + "BriefDescription": "Number of TXREQ flits dispatched. This event measures the total request bandwidth.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "rnid_txreq_flits_retried", + "EventidCode": "0x7", + "NodeType": "0xa", + "BriefDescription": "Number of retried TXREQ flits dispatched. This event measures the retry rate.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "sbsx_txrsp_retryack", + "EventidCode": "0x4", + "NodeType": "0x7", + "BriefDescription": "Number of RXREQ flits dispatched. This event is a measure of the retry rate.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "sbsx_txdat_flitv", + "EventidCode": "0x5", + "NodeType": "0x7", + "BriefDescription": "Number of TXDAT flits dispatched from XP to SBSX. This event is a measure of the write bandwidth.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "sbsx_arvalid_no_arready", + "EventidCode": "0x21", + "NodeType": "0x7", + "BriefDescription": "Number of cycles the SBSX bridge is stalled because of backpressure on AR channel.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "sbsx_awvalid_no_awready", + "EventidCode": "0x22", + "NodeType": "0x7", + "BriefDescription": "Number of cycles the SBSX bridge is stalled because of backpressure on AW channel.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "sbsx_wvalid_no_wready", + "EventidCode": "0x23", + "NodeType": "0x7", + "BriefDescription": "Number of cycles the SBSX bridge is stalled because of backpressure on W channel.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_txrsp_retryack", + "EventidCode": "0x2a", + "NodeType": "0x4", + "BriefDescription": "Number of RXREQ flits dispatched. This event is a measure of the retry rate.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_arvalid_no_arready", + "EventidCode": "0x2b", + "NodeType": "0x4", + "BriefDescription": "Number of cycles the HN-I bridge is stalled because of backpressure on AR channel.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_arready_no_arvalid", + "EventidCode": "0x2c", + "NodeType": "0x4", + "BriefDescription": "Number of cycles the AR channel is waiting for new requests from HN-I bridge.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_awvalid_no_awready", + "EventidCode": "0x2d", + "NodeType": "0x4", + "BriefDescription": "Number of cycles the HN-I bridge is stalled because of backpressure on AW channel.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_awready_no_awvalid", + "EventidCode": "0x2e", + "NodeType": "0x4", + "BriefDescription": "Number of cycles the AW channel is waiting for new requests from HN-I bridge.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_wvalid_no_wready", + "EventidCode": "0x2f", + "NodeType": "0x4", + "BriefDescription": "Number of cycles the HN-I bridge is stalled because of backpressure on W channel.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "EventName": "hni_txdat_stall", + "EventidCode": "0x30", + "NodeType": "0x4", + "BriefDescription": "TXDAT valid but no link credit available.", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/cmn/sys/metric.json b/tools/perf/pmu-events/arch/arm64/arm/cmn/sys/metric.json new file mode 100644 index 000000000000..f7823bd265db --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/cmn/sys/metric.json @@ -0,0 +1,74 @@ +[ + { + "MetricName": "slc_miss_rate", + "BriefDescription": "The system level cache miss rate.", + "MetricGroup": "cmn", + "MetricExpr": "hnf_cache_miss / hnf_slc_sf_cache_access", + "ScaleUnit": "100%", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "hnf_message_retry_rate", + "BriefDescription": "HN-F message retry rate indicates whether a lack of credits is causing the bottlenecks.", + "MetricGroup": "cmn", + "MetricExpr": "hnf_pocq_retry / hnf_pocq_reqs_recvd", + "ScaleUnit": "100%", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "sf_hit_rate", + "BriefDescription": "Snoop filter hit rate can be used to measure the snoop filter efficiency.", + "MetricGroup": "cmn", + "MetricExpr": "hnf_sf_hit / hnf_slc_sf_cache_access", + "ScaleUnit": "100%", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "mc_message_retry_rate", + "BriefDescription": "The memory controller request retries rate indicates whether the memory controller is the bottleneck.", + "MetricGroup": "cmn", + "MetricExpr": "hnf_mc_retries / hnf_mc_reqs", + "ScaleUnit": "100%", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "rni_actual_read_bandwidth.all", + "BriefDescription": "This event measure the actual bandwidth that RN-I bridge sends to the interconnect.", + "MetricGroup": "cmn", + "MetricExpr": "rnid_rxdat_flits * 32 / 1e6 / duration_time", + "ScaleUnit": "1MB/s", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "rni_actual_write_bandwidth.all", + "BriefDescription": "This event measures the actual write bandwidth at RN-I bridges.", + "MetricGroup": "cmn", + "MetricExpr": "rnid_txdat_flits * 32 / 1e6 / duration_time", + "ScaleUnit": "1MB/s", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "rni_retry_rate", + "BriefDescription": "RN-I bridge retry rate indicates whether the memory controller is the bottleneck.", + "MetricGroup": "cmn", + "MetricExpr": "rnid_txreq_flits_retried / rnid_txreq_flits_total", + "ScaleUnit": "100%", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + }, + { + "MetricName": "sbsx_actual_write_bandwidth.all", + "BriefDescription": "sbsx actual write bandwidth.", + "MetricGroup": "cmn", + "MetricExpr": "sbsx_txdat_flitv * 32 / 1e6 / duration_time", + "ScaleUnit": "1MB/s", + "Unit": "arm_cmn", + "Compat": "(434|436|43c|43a).*" + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/branch.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/branch.json deleted file mode 100644 index 79f2016c53b0..000000000000 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/branch.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "ArchStdEvent": "BR_MIS_PRED" - }, - { - "ArchStdEvent": "BR_PRED" - } -] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/bus.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/bus.json index 579c1c993d17..2e11a8c4a484 100644 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/bus.json +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/bus.json @@ -1,20 +1,18 @@ [ { - "ArchStdEvent": "CPU_CYCLES" + "ArchStdEvent": "BUS_ACCESS", + "PublicDescription": "Counts memory transactions issued by the CPU to the external bus, including snoop requests and snoop responses. Each beat of data is counted individually." }, { - "ArchStdEvent": "BUS_ACCESS" + "ArchStdEvent": "BUS_CYCLES", + "PublicDescription": "Counts bus cycles in the CPU. Bus cycles represent a clock cycle in which a transaction could be sent or received on the interface from the CPU to the external bus. Since that interface is driven at the same clock speed as the CPU, this event is a duplicate of CPU_CYCLES." }, { - "ArchStdEvent": "BUS_CYCLES" + "ArchStdEvent": "BUS_ACCESS_RD", + "PublicDescription": "Counts memory read transactions seen on the external bus. Each beat of data is counted individually." }, { - "ArchStdEvent": "BUS_ACCESS_RD" - }, - { - "ArchStdEvent": "BUS_ACCESS_WR" - }, - { - "ArchStdEvent": "CNT_CYCLES" + "ArchStdEvent": "BUS_ACCESS_WR", + "PublicDescription": "Counts memory write transactions seen on the external bus. Each beat of data is counted individually." } ] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/cache.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/cache.json deleted file mode 100644 index 0141f749bff3..000000000000 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/cache.json +++ /dev/null @@ -1,155 +0,0 @@ -[ - { - "ArchStdEvent": "L1I_CACHE_REFILL" - }, - { - "ArchStdEvent": "L1I_TLB_REFILL" - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL" - }, - { - "ArchStdEvent": "L1D_CACHE" - }, - { - "ArchStdEvent": "L1D_TLB_REFILL" - }, - { - "ArchStdEvent": "L1I_CACHE" - }, - { - "ArchStdEvent": "L1D_CACHE_WB" - }, - { - "ArchStdEvent": "L2D_CACHE" - }, - { - "ArchStdEvent": "L2D_CACHE_REFILL" - }, - { - "ArchStdEvent": "L2D_CACHE_WB" - }, - { - "ArchStdEvent": "L2D_CACHE_ALLOCATE" - }, - { - "ArchStdEvent": "L1D_TLB" - }, - { - "ArchStdEvent": "L1I_TLB" - }, - { - "ArchStdEvent": "L3D_CACHE_ALLOCATE" - }, - { - "ArchStdEvent": "L3D_CACHE_REFILL" - }, - { - "ArchStdEvent": "L3D_CACHE" - }, - { - "ArchStdEvent": "L2D_TLB_REFILL" - }, - { - "ArchStdEvent": "L2D_TLB" - }, - { - "ArchStdEvent": "DTLB_WALK" - }, - { - "ArchStdEvent": "ITLB_WALK" - }, - { - "ArchStdEvent": "LL_CACHE_RD" - }, - { - "ArchStdEvent": "LL_CACHE_MISS_RD" - }, - { - "ArchStdEvent": "L1D_CACHE_LMISS_RD" - }, - { - "ArchStdEvent": "L1D_CACHE_RD" - }, - { - "ArchStdEvent": "L1D_CACHE_WR" - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL_RD" - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL_WR" - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL_INNER" - }, - { - "ArchStdEvent": "L1D_CACHE_REFILL_OUTER" - }, - { - "ArchStdEvent": "L1D_CACHE_WB_VICTIM" - }, - { - "ArchStdEvent": "L1D_CACHE_WB_CLEAN" - }, - { - "ArchStdEvent": "L1D_CACHE_INVAL" - }, - { - "ArchStdEvent": "L1D_TLB_REFILL_RD" - }, - { - "ArchStdEvent": "L1D_TLB_REFILL_WR" - }, - { - "ArchStdEvent": "L1D_TLB_RD" - }, - { - "ArchStdEvent": "L1D_TLB_WR" - }, - { - "ArchStdEvent": "L2D_CACHE_RD" - }, - { - "ArchStdEvent": "L2D_CACHE_WR" - }, - { - "ArchStdEvent": "L2D_CACHE_REFILL_RD" - }, - { - "ArchStdEvent": "L2D_CACHE_REFILL_WR" - }, - { - "ArchStdEvent": "L2D_CACHE_WB_VICTIM" - }, - { - "ArchStdEvent": "L2D_CACHE_WB_CLEAN" - }, - { - "ArchStdEvent": "L2D_CACHE_INVAL" - }, - { - "ArchStdEvent": "L2D_TLB_REFILL_RD" - }, - { - "ArchStdEvent": "L2D_TLB_REFILL_WR" - }, - { - "ArchStdEvent": "L2D_TLB_RD" - }, - { - "ArchStdEvent": "L2D_TLB_WR" - }, - { - "ArchStdEvent": "L3D_CACHE_RD" - }, - { - "ArchStdEvent": "L1I_CACHE_LMISS" - }, - { - "ArchStdEvent": "L2D_CACHE_LMISS_RD" - }, - { - "ArchStdEvent": "L3D_CACHE_LMISS_RD" - } -] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/exception.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/exception.json index 344a2d552ad5..4404b8e91690 100644 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/exception.json +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/exception.json @@ -1,47 +1,62 @@ [ { - "ArchStdEvent": "EXC_TAKEN" + "ArchStdEvent": "EXC_TAKEN", + "PublicDescription": "Counts any taken architecturally visible exceptions such as IRQ, FIQ, SError, and other synchronous exceptions. Exceptions are counted whether or not they are taken locally." }, { - "ArchStdEvent": "MEMORY_ERROR" + "ArchStdEvent": "EXC_RETURN", + "PublicDescription": "Counts any architecturally executed exception return instructions. Eg: AArch64: ERET" }, { - "ArchStdEvent": "EXC_UNDEF" + "ArchStdEvent": "EXC_UNDEF", + "PublicDescription": "Counts the number of synchronous exceptions which are taken locally that are due to attempting to execute an instruction that is UNDEFINED. Attempting to execute instruction bit patterns that have not been allocated. Attempting to execute instructions when they are disabled. Attempting to execute instructions at an inappropriate Exception level. Attempting to execute an instruction when the value of PSTATE.IL is 1." }, { - "ArchStdEvent": "EXC_SVC" + "ArchStdEvent": "EXC_SVC", + "PublicDescription": "Counts SVC exceptions taken locally." }, { - "ArchStdEvent": "EXC_PABORT" + "ArchStdEvent": "EXC_PABORT", + "PublicDescription": "Counts synchronous exceptions that are taken locally and caused by Instruction Aborts." }, { - "ArchStdEvent": "EXC_DABORT" + "ArchStdEvent": "EXC_DABORT", + "PublicDescription": "Counts exceptions that are taken locally and are caused by data aborts or SErrors. Conditions that could cause those exceptions are attempting to read or write memory where the MMU generates a fault, attempting to read or write memory with a misaligned address, interrupts from the nSEI inputs and internally generated SErrors." }, { - "ArchStdEvent": "EXC_IRQ" + "ArchStdEvent": "EXC_IRQ", + "PublicDescription": "Counts IRQ exceptions including the virtual IRQs that are taken locally." }, { - "ArchStdEvent": "EXC_FIQ" + "ArchStdEvent": "EXC_FIQ", + "PublicDescription": "Counts FIQ exceptions including the virtual FIQs that are taken locally." }, { - "ArchStdEvent": "EXC_SMC" + "ArchStdEvent": "EXC_SMC", + "PublicDescription": "Counts SMC exceptions take to EL3." }, { - "ArchStdEvent": "EXC_HVC" + "ArchStdEvent": "EXC_HVC", + "PublicDescription": "Counts HVC exceptions taken to EL2." }, { - "ArchStdEvent": "EXC_TRAP_PABORT" + "ArchStdEvent": "EXC_TRAP_PABORT", + "PublicDescription": "Counts exceptions which are traps not taken locally and are caused by Instruction Aborts. For example, attempting to execute an instruction with a misaligned PC." }, { - "ArchStdEvent": "EXC_TRAP_DABORT" + "ArchStdEvent": "EXC_TRAP_DABORT", + "PublicDescription": "Counts exceptions which are traps not taken locally and are caused by Data Aborts or SError interrupts. Conditions that could cause those exceptions are:\n\n1. Attempting to read or write memory where the MMU generates a fault,\n2. Attempting to read or write memory with a misaligned address,\n3. Interrupts from the SEI input.\n4. internally generated SErrors." }, { - "ArchStdEvent": "EXC_TRAP_OTHER" + "ArchStdEvent": "EXC_TRAP_OTHER", + "PublicDescription": "Counts the number of synchronous trap exceptions which are not taken locally and are not SVC, SMC, HVC, data aborts, Instruction Aborts, or interrupts." }, { - "ArchStdEvent": "EXC_TRAP_IRQ" + "ArchStdEvent": "EXC_TRAP_IRQ", + "PublicDescription": "Counts IRQ exceptions including the virtual IRQs that are not taken locally." }, { - "ArchStdEvent": "EXC_TRAP_FIQ" + "ArchStdEvent": "EXC_TRAP_FIQ", + "PublicDescription": "Counts FIQs which are not taken locally but taken from EL0, EL1,\n or EL2 to EL3 (which would be the normal behavior for FIQs when not executing\n in EL3)." } ] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/fp_operation.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/fp_operation.json new file mode 100644 index 000000000000..a09e226e7138 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/fp_operation.json @@ -0,0 +1,10 @@ +[ + { + "ArchStdEvent": "FP_SCALE_OPS_SPEC", + "PublicDescription": "Counts speculatively executed scalable single precision floating point operations." + }, + { + "ArchStdEvent": "FP_FIXED_OPS_SPEC", + "PublicDescription": "Counts speculatively executed non-scalable single precision floating point operations." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/general.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/general.json new file mode 100644 index 000000000000..428810f855b8 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/general.json @@ -0,0 +1,10 @@ +[ + { + "ArchStdEvent": "CPU_CYCLES", + "PublicDescription": "Counts CPU clock cycles (not timer cycles). The clock measured by this event is defined as the physical clock driving the CPU logic." + }, + { + "ArchStdEvent": "CNT_CYCLES", + "PublicDescription": "Counts constant frequency cycles" + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/instruction.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/instruction.json deleted file mode 100644 index e29b88fb7f24..000000000000 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/instruction.json +++ /dev/null @@ -1,119 +0,0 @@ -[ - { - "ArchStdEvent": "SW_INCR" - }, - { - "ArchStdEvent": "INST_RETIRED" - }, - { - "ArchStdEvent": "EXC_RETURN" - }, - { - "ArchStdEvent": "CID_WRITE_RETIRED" - }, - { - "ArchStdEvent": "INST_SPEC" - }, - { - "ArchStdEvent": "TTBR_WRITE_RETIRED" - }, - { - "ArchStdEvent": "BR_RETIRED" - }, - { - "ArchStdEvent": "BR_MIS_PRED_RETIRED" - }, - { - "ArchStdEvent": "OP_RETIRED" - }, - { - "ArchStdEvent": "OP_SPEC" - }, - { - "ArchStdEvent": "LDREX_SPEC" - }, - { - "ArchStdEvent": "STREX_PASS_SPEC" - }, - { - "ArchStdEvent": "STREX_FAIL_SPEC" - }, - { - "ArchStdEvent": "STREX_SPEC" - }, - { - "ArchStdEvent": "LD_SPEC" - }, - { - "ArchStdEvent": "ST_SPEC" - }, - { - "ArchStdEvent": "DP_SPEC" - }, - { - "ArchStdEvent": "ASE_SPEC" - }, - { - "ArchStdEvent": "VFP_SPEC" - }, - { - "ArchStdEvent": "PC_WRITE_SPEC" - }, - { - "ArchStdEvent": "CRYPTO_SPEC" - }, - { - "ArchStdEvent": "BR_IMMED_SPEC" - }, - { - "ArchStdEvent": "BR_RETURN_SPEC" - }, - { - "ArchStdEvent": "BR_INDIRECT_SPEC" - }, - { - "ArchStdEvent": "ISB_SPEC" - }, - { - "ArchStdEvent": "DSB_SPEC" - }, - { - "ArchStdEvent": "DMB_SPEC" - }, - { - "ArchStdEvent": "RC_LD_SPEC" - }, - { - "ArchStdEvent": "RC_ST_SPEC" - }, - { - "ArchStdEvent": "ASE_INST_SPEC" - }, - { - "ArchStdEvent": "SVE_INST_SPEC" - }, - { - "ArchStdEvent": "SVE_PRED_SPEC" - }, - { - "ArchStdEvent": "SVE_PRED_EMPTY_SPEC" - }, - { - "ArchStdEvent": "SVE_PRED_FULL_SPEC" - }, - { - "ArchStdEvent": "SVE_PRED_PARTIAL_SPEC" - }, - { - "ArchStdEvent": "SVE_LDFF_SPEC" - }, - { - "ArchStdEvent": "SVE_LDFF_FAULT_SPEC" - }, - { - "ArchStdEvent": "FP_SCALE_OPS_SPEC" - }, - { - "ArchStdEvent": "FP_FIXED_OPS_SPEC" - } -] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1d_cache.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1d_cache.json new file mode 100644 index 000000000000..ed83e1c5affe --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1d_cache.json @@ -0,0 +1,54 @@ +[ + { + "ArchStdEvent": "L1D_CACHE_REFILL", + "PublicDescription": "Counts level 1 data cache refills caused by speculatively executed load or store operations that missed in the level 1 data cache. This event only counts one event per cache line. This event does not count cache line allocations from preload instructions or from hardware cache prefetching." + }, + { + "ArchStdEvent": "L1D_CACHE", + "PublicDescription": "Counts level 1 data cache accesses from any load/store operations. Atomic operations that resolve in the CPUs caches (near atomic operations) counts as both a write access and read access. Each access to a cache line is counted including the multiple accesses caused by single instructions such as LDM or STM. Each access to other level 1 data or unified memory structures, for example refill buffers, write buffers, and write-back buffers, are also counted." + }, + { + "ArchStdEvent": "L1D_CACHE_WB", + "PublicDescription": "Counts write-backs of dirty data from the L1 data cache to the L2 cache. This occurs when either a dirty cache line is evicted from L1 data cache and allocated in the L2 cache or dirty data is written to the L2 and possibly to the next level of cache. This event counts both victim cache line evictions and cache write-backs from snoops or cache maintenance operations. The following cache operations are not counted:\n\n1. Invalidations which do not result in data being transferred out of the L1 (such as evictions of clean data),\n2. Full line writes which write to L2 without writing L1, such as write streaming mode." + }, + { + "ArchStdEvent": "L1D_CACHE_LMISS_RD", + "PublicDescription": "Counts cache line refills into the level 1 data cache from any memory read operations, that incurred additional latency." + }, + { + "ArchStdEvent": "L1D_CACHE_RD", + "PublicDescription": "Counts level 1 data cache accesses from any load operation. Atomic load operations that resolve in the CPUs caches counts as both a write access and read access." + }, + { + "ArchStdEvent": "L1D_CACHE_WR", + "PublicDescription": "Counts level 1 data cache accesses generated by store operations. This event also counts accesses caused by a DC ZVA (data cache zero, specified by virtual address) instruction. Near atomic operations that resolve in the CPUs caches count as a write access and read access." + }, + { + "ArchStdEvent": "L1D_CACHE_REFILL_RD", + "PublicDescription": "Counts level 1 data cache refills caused by speculatively executed load instructions where the memory read operation misses in the level 1 data cache. This event only counts one event per cache line." + }, + { + "ArchStdEvent": "L1D_CACHE_REFILL_WR", + "PublicDescription": "Counts level 1 data cache refills caused by speculatively executed store instructions where the memory write operation misses in the level 1 data cache. This event only counts one event per cache line." + }, + { + "ArchStdEvent": "L1D_CACHE_REFILL_INNER", + "PublicDescription": "Counts level 1 data cache refills where the cache line data came from caches inside the immediate cluster of the core." + }, + { + "ArchStdEvent": "L1D_CACHE_REFILL_OUTER", + "PublicDescription": "Counts level 1 data cache refills for which the cache line data came from outside the immediate cluster of the core, like an SLC in the system interconnect or DRAM." + }, + { + "ArchStdEvent": "L1D_CACHE_WB_VICTIM", + "PublicDescription": "Counts dirty cache line evictions from the level 1 data cache caused by a new cache line allocation. This event does not count evictions caused by cache maintenance operations." + }, + { + "ArchStdEvent": "L1D_CACHE_WB_CLEAN", + "PublicDescription": "Counts write-backs from the level 1 data cache that are a result of a coherency operation made by another CPU. Event count includes cache maintenance operations." + }, + { + "ArchStdEvent": "L1D_CACHE_INVAL", + "PublicDescription": "Counts each explicit invalidation of a cache line in the level 1 data cache caused by:\n\n- Cache Maintenance Operations (CMO) that operate by a virtual address.\n- Broadcast cache coherency operations from another CPU in the system.\n\nThis event does not count for the following conditions:\n\n1. A cache refill invalidates a cache line.\n2. A CMO which is executed on that CPU and invalidates a cache line specified by set/way.\n\nNote that CMOs that operate by set/way cannot be broadcast from one CPU to another." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1i_cache.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1i_cache.json new file mode 100644 index 000000000000..633f1030359d --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l1i_cache.json @@ -0,0 +1,14 @@ +[ + { + "ArchStdEvent": "L1I_CACHE_REFILL", + "PublicDescription": "Counts cache line refills in the level 1 instruction cache caused by a missed instruction fetch. Instruction fetches may include accessing multiple instructions, but the single cache line allocation is counted once." + }, + { + "ArchStdEvent": "L1I_CACHE", + "PublicDescription": "Counts instruction fetches which access the level 1 instruction cache. Instruction cache accesses caused by cache maintenance operations are not counted." + }, + { + "ArchStdEvent": "L1I_CACHE_LMISS", + "PublicDescription": "Counts cache line refills into the level 1 instruction cache, that incurred additional latency." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l2_cache.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l2_cache.json new file mode 100644 index 000000000000..0e31d0daf88b --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l2_cache.json @@ -0,0 +1,50 @@ +[ + { + "ArchStdEvent": "L2D_CACHE", + "PublicDescription": "Counts level 2 cache accesses. level 2 cache is a unified cache for data and instruction accesses. Accesses are for misses in the first level caches or translation resolutions due to accesses. This event also counts write back of dirty data from level 1 data cache to the L2 cache." + }, + { + "ArchStdEvent": "L2D_CACHE_REFILL", + "PublicDescription": "Counts cache line refills into the level 2 cache. level 2 cache is a unified cache for data and instruction accesses. Accesses are for misses in the level 1 caches or translation resolutions due to accesses." + }, + { + "ArchStdEvent": "L2D_CACHE_WB", + "PublicDescription": "Counts write-backs of data from the L2 cache to outside the CPU. This includes snoops to the L2 (from other CPUs) which return data even if the snoops cause an invalidation. L2 cache line invalidations which do not write data outside the CPU and snoops which return data from an L1 cache are not counted. Data would not be written outside the cache when invalidating a clean cache line." + }, + { + "ArchStdEvent": "L2D_CACHE_ALLOCATE", + "PublicDescription": "TBD" + }, + { + "ArchStdEvent": "L2D_CACHE_RD", + "PublicDescription": "Counts level 2 cache accesses due to memory read operations. level 2 cache is a unified cache for data and instruction accesses, accesses are for misses in the level 1 caches or translation resolutions due to accesses." + }, + { + "ArchStdEvent": "L2D_CACHE_WR", + "PublicDescription": "Counts level 2 cache accesses due to memory write operations. level 2 cache is a unified cache for data and instruction accesses, accesses are for misses in the level 1 caches or translation resolutions due to accesses." + }, + { + "ArchStdEvent": "L2D_CACHE_REFILL_RD", + "PublicDescription": "Counts refills for memory accesses due to memory read operation counted by L2D_CACHE_RD. level 2 cache is a unified cache for data and instruction accesses, accesses are for misses in the level 1 caches or translation resolutions due to accesses." + }, + { + "ArchStdEvent": "L2D_CACHE_REFILL_WR", + "PublicDescription": "Counts refills for memory accesses due to memory write operation counted by L2D_CACHE_WR. level 2 cache is a unified cache for data and instruction accesses, accesses are for misses in the level 1 caches or translation resolutions due to accesses." + }, + { + "ArchStdEvent": "L2D_CACHE_WB_VICTIM", + "PublicDescription": "Counts evictions from the level 2 cache because of a line being allocated into the L2 cache." + }, + { + "ArchStdEvent": "L2D_CACHE_WB_CLEAN", + "PublicDescription": "Counts write-backs from the level 2 cache that are a result of either:\n\n1. Cache maintenance operations,\n\n2. Snoop responses or,\n\n3. Direct cache transfers to another CPU due to a forwarding snoop request." + }, + { + "ArchStdEvent": "L2D_CACHE_INVAL", + "PublicDescription": "Counts each explicit invalidation of a cache line in the level 2 cache by cache maintenance operations that operate by a virtual address, or by external coherency operations. This event does not count if either:\n\n1. A cache refill invalidates a cache line or,\n2. A Cache Maintenance Operation (CMO), which invalidates a cache line specified by set/way, is executed on that CPU.\n\nCMOs that operate by set/way cannot be broadcast from one CPU to another." + }, + { + "ArchStdEvent": "L2D_CACHE_LMISS_RD", + "PublicDescription": "Counts cache line refills into the level 2 unified cache from any memory read operations that incurred additional latency." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l3_cache.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l3_cache.json new file mode 100644 index 000000000000..45bfba532df7 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/l3_cache.json @@ -0,0 +1,22 @@ +[ + { + "ArchStdEvent": "L3D_CACHE_ALLOCATE", + "PublicDescription": "Counts level 3 cache line allocates that do not fetch data from outside the level 3 data or unified cache. For example, allocates due to streaming stores." + }, + { + "ArchStdEvent": "L3D_CACHE_REFILL", + "PublicDescription": "Counts level 3 accesses that receive data from outside the L3 cache." + }, + { + "ArchStdEvent": "L3D_CACHE", + "PublicDescription": "Counts level 3 cache accesses. level 3 cache is a unified cache for data and instruction accesses. Accesses are for misses in the lower level caches or translation resolutions due to accesses." + }, + { + "ArchStdEvent": "L3D_CACHE_RD", + "PublicDescription": "TBD" + }, + { + "ArchStdEvent": "L3D_CACHE_LMISS_RD", + "PublicDescription": "Counts any cache line refill into the level 3 cache from memory read operations that incurred additional latency." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/ll_cache.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/ll_cache.json new file mode 100644 index 000000000000..bb712d57d58a --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/ll_cache.json @@ -0,0 +1,10 @@ +[ + { + "ArchStdEvent": "LL_CACHE_RD", + "PublicDescription": "Counts read transactions that were returned from outside the core cluster. This event counts when the system register CPUECTLR.EXTLLC bit is set. This event counts read transactions returned from outside the core if those transactions are either hit in the system level cache or missed in the SLC and are returned from any other external sources." + }, + { + "ArchStdEvent": "LL_CACHE_MISS_RD", + "PublicDescription": "Counts read transactions that were returned from outside the core cluster but missed in the system level cache. This event counts when the system register CPUECTLR.EXTLLC bit is set. This event counts read transactions returned from outside the core if those transactions are missed in the System level Cache. The data source of the transaction is indicated by a field in the CHI transaction returning to the CPU. This event does not count reads caused by cache maintenance operations." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/memory.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/memory.json index 5aff6e93c1ad..9041f6e0befb 100644 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/memory.json +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/memory.json @@ -1,23 +1,22 @@ [ { - "ArchStdEvent": "MEM_ACCESS" + "ArchStdEvent": "MEM_ACCESS", + "PublicDescription": "Counts memory accesses issued by the CPU load store unit, where those accesses are issued due to load or store operations. This event counts memory accesses no matter whether the data is received from any level of cache hierarchy or external memory. If memory accesses are broken up into smaller transactions than what were specified in the load or store instructions, then the event counts those smaller memory transactions." }, { - "ArchStdEvent": "REMOTE_ACCESS" + "ArchStdEvent": "MEMORY_ERROR", + "PublicDescription": "Counts any detected correctable or uncorrectable physical memory errors (ECC or parity) in protected CPUs RAMs. On the core, this event counts errors in the caches (including data and tag rams). Any detected memory error (from either a speculative and abandoned access, or an architecturally executed access) is counted. Note that errors are only detected when the actual protected memory is accessed by an operation." }, { - "ArchStdEvent": "MEM_ACCESS_RD" + "ArchStdEvent": "REMOTE_ACCESS", + "PublicDescription": "Counts accesses to another chip, which is implemented as a different CMN mesh in the system. If the CHI bus response back to the core indicates that the data source is from another chip (mesh), then the counter is updated. If no data is returned, even if the system snoops another chip/mesh, then the counter is not updated." }, { - "ArchStdEvent": "MEM_ACCESS_WR" + "ArchStdEvent": "MEM_ACCESS_RD", + "PublicDescription": "Counts memory accesses issued by the CPU due to load operations. The event counts any memory load access, no matter whether the data is received from any level of cache hierarchy or external memory. The event also counts atomic load operations. If memory accesses are broken up by the load/store unit into smaller transactions that are issued by the bus interface, then the event counts those smaller transactions." }, { - "ArchStdEvent": "UNALIGNED_LD_SPEC" - }, - { - "ArchStdEvent": "UNALIGNED_ST_SPEC" - }, - { - "ArchStdEvent": "UNALIGNED_LDST_SPEC" + "ArchStdEvent": "MEM_ACCESS_WR", + "PublicDescription": "Counts memory accesses issued by the CPU due to store operations. The event counts any memory store access, no matter whether the data is located in any level of cache or external memory. The event also counts atomic load and store operations. If memory accesses are broken up by the load/store unit into smaller transactions that are issued by the bus interface, then the event counts those smaller transactions." } ] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/metrics.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/metrics.json new file mode 100644 index 000000000000..3fd8fefec46a --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/metrics.json @@ -0,0 +1,233 @@ +[ + { + "ArchStdEvent": "backend_bound" + }, + { + "MetricName": "backend_stalled_cycles", + "MetricExpr": "((STALL_BACKEND / CPU_CYCLES) * 100)", + "BriefDescription": "This metric is the percentage of cycles that were stalled due to resource constraints in the backend unit of the processor.", + "MetricGroup": "Cycle_Accounting", + "ScaleUnit": "1percent of cycles" + }, + { + "ArchStdEvent": "bad_speculation", + "MetricExpr": "(100 * (((1 - (OP_RETIRED / OP_SPEC)) * (1 - (STALL_SLOT / (CPU_CYCLES * 8)))) + ((BR_MIS_PRED * 4) / CPU_CYCLES)))" + }, + { + "MetricName": "branch_misprediction_ratio", + "MetricExpr": "(BR_MIS_PRED_RETIRED / BR_RETIRED)", + "BriefDescription": "This metric measures the ratio of branches mispredicted to the total number of branches architecturally executed. This gives an indication of the effectiveness of the branch prediction unit.", + "MetricGroup": "Miss_Ratio;Branch_Effectiveness", + "ScaleUnit": "1per branch" + }, + { + "MetricName": "branch_mpki", + "MetricExpr": "((BR_MIS_PRED_RETIRED / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of branch mispredictions per thousand instructions executed.", + "MetricGroup": "MPKI;Branch_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "branch_percentage", + "MetricExpr": "(((BR_IMMED_SPEC + BR_INDIRECT_SPEC) / INST_SPEC) * 100)", + "BriefDescription": "This metric measures branch operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + }, + { + "MetricName": "crypto_percentage", + "MetricExpr": "((CRYPTO_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures crypto operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + }, + { + "MetricName": "dtlb_mpki", + "MetricExpr": "((DTLB_WALK / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of data TLB Walks per thousand instructions executed.", + "MetricGroup": "MPKI;DTLB_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "dtlb_walk_ratio", + "MetricExpr": "(DTLB_WALK / L1D_TLB)", + "BriefDescription": "This metric measures the ratio of data TLB Walks to the total number of data TLB accesses. This gives an indication of the effectiveness of the data TLB accesses.", + "MetricGroup": "Miss_Ratio;DTLB_Effectiveness", + "ScaleUnit": "1per TLB access" + }, + { + "ArchStdEvent": "frontend_bound", + "MetricExpr": "(100 * ((STALL_SLOT_FRONTEND / (CPU_CYCLES * 8)) - ((BR_MIS_PRED * 4) / CPU_CYCLES)))" + }, + { + "MetricName": "frontend_stalled_cycles", + "MetricExpr": "((STALL_FRONTEND / CPU_CYCLES) * 100)", + "BriefDescription": "This metric is the percentage of cycles that were stalled due to resource constraints in the frontend unit of the processor.", + "MetricGroup": "Cycle_Accounting", + "ScaleUnit": "1percent of cycles" + }, + { + "MetricName": "integer_dp_percentage", + "MetricExpr": "((DP_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures scalar integer operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + }, + { + "MetricName": "ipc", + "MetricExpr": "(INST_RETIRED / CPU_CYCLES)", + "BriefDescription": "This metric measures the number of instructions retired per cycle.", + "MetricGroup": "General", + "ScaleUnit": "1per cycle" + }, + { + "MetricName": "itlb_mpki", + "MetricExpr": "((ITLB_WALK / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of instruction TLB Walks per thousand instructions executed.", + "MetricGroup": "MPKI;ITLB_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "itlb_walk_ratio", + "MetricExpr": "(ITLB_WALK / L1I_TLB)", + "BriefDescription": "This metric measures the ratio of instruction TLB Walks to the total number of instruction TLB accesses. This gives an indication of the effectiveness of the instruction TLB accesses.", + "MetricGroup": "Miss_Ratio;ITLB_Effectiveness", + "ScaleUnit": "1per TLB access" + }, + { + "MetricName": "l1d_cache_miss_ratio", + "MetricExpr": "(L1D_CACHE_REFILL / L1D_CACHE)", + "BriefDescription": "This metric measures the ratio of level 1 data cache accesses missed to the total number of level 1 data cache accesses. This gives an indication of the effectiveness of the level 1 data cache.", + "MetricGroup": "Miss_Ratio;L1D_Cache_Effectiveness", + "ScaleUnit": "1per cache access" + }, + { + "MetricName": "l1d_cache_mpki", + "MetricExpr": "((L1D_CACHE_REFILL / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of level 1 data cache accesses missed per thousand instructions executed.", + "MetricGroup": "MPKI;L1D_Cache_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "l1d_tlb_miss_ratio", + "MetricExpr": "(L1D_TLB_REFILL / L1D_TLB)", + "BriefDescription": "This metric measures the ratio of level 1 data TLB accesses missed to the total number of level 1 data TLB accesses. This gives an indication of the effectiveness of the level 1 data TLB.", + "MetricGroup": "Miss_Ratio;DTLB_Effectiveness", + "ScaleUnit": "1per TLB access" + }, + { + "MetricName": "l1d_tlb_mpki", + "MetricExpr": "((L1D_TLB_REFILL / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of level 1 instruction TLB accesses missed per thousand instructions executed.", + "MetricGroup": "MPKI;DTLB_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "l1i_cache_miss_ratio", + "MetricExpr": "(L1I_CACHE_REFILL / L1I_CACHE)", + "BriefDescription": "This metric measures the ratio of level 1 instruction cache accesses missed to the total number of level 1 instruction cache accesses. This gives an indication of the effectiveness of the level 1 instruction cache.", + "MetricGroup": "Miss_Ratio;L1I_Cache_Effectiveness", + "ScaleUnit": "1per cache access" + }, + { + "MetricName": "l1i_cache_mpki", + "MetricExpr": "((L1I_CACHE_REFILL / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of level 1 instruction cache accesses missed per thousand instructions executed.", + "MetricGroup": "MPKI;L1I_Cache_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "l1i_tlb_miss_ratio", + "MetricExpr": "(L1I_TLB_REFILL / L1I_TLB)", + "BriefDescription": "This metric measures the ratio of level 1 instruction TLB accesses missed to the total number of level 1 instruction TLB accesses. This gives an indication of the effectiveness of the level 1 instruction TLB.", + "MetricGroup": "Miss_Ratio;ITLB_Effectiveness", + "ScaleUnit": "1per TLB access" + }, + { + "MetricName": "l1i_tlb_mpki", + "MetricExpr": "((L1I_TLB_REFILL / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of level 1 instruction TLB accesses missed per thousand instructions executed.", + "MetricGroup": "MPKI;ITLB_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "l2_cache_miss_ratio", + "MetricExpr": "(L2D_CACHE_REFILL / L2D_CACHE)", + "BriefDescription": "This metric measures the ratio of level 2 cache accesses missed to the total number of level 2 cache accesses. This gives an indication of the effectiveness of the level 2 cache, which is a unified cache that stores both data and instruction. Note that cache accesses in this cache are either data memory access or instruction fetch as this is a unified cache.", + "MetricGroup": "Miss_Ratio;L2_Cache_Effectiveness", + "ScaleUnit": "1per cache access" + }, + { + "MetricName": "l2_cache_mpki", + "MetricExpr": "((L2D_CACHE_REFILL / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of level 2 unified cache accesses missed per thousand instructions executed. Note that cache accesses in this cache are either data memory access or instruction fetch as this is a unified cache.", + "MetricGroup": "MPKI;L2_Cache_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "l2_tlb_miss_ratio", + "MetricExpr": "(L2D_TLB_REFILL / L2D_TLB)", + "BriefDescription": "This metric measures the ratio of level 2 unified TLB accesses missed to the total number of level 2 unified TLB accesses. This gives an indication of the effectiveness of the level 2 TLB.", + "MetricGroup": "Miss_Ratio;ITLB_Effectiveness;DTLB_Effectiveness", + "ScaleUnit": "1per TLB access" + }, + { + "MetricName": "l2_tlb_mpki", + "MetricExpr": "((L2D_TLB_REFILL / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of level 2 unified TLB accesses missed per thousand instructions executed.", + "MetricGroup": "MPKI;ITLB_Effectiveness;DTLB_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "ll_cache_read_hit_ratio", + "MetricExpr": "((LL_CACHE_RD - LL_CACHE_MISS_RD) / LL_CACHE_RD)", + "BriefDescription": "This metric measures the ratio of last level cache read accesses hit in the cache to the total number of last level cache accesses. This gives an indication of the effectiveness of the last level cache for read traffic. Note that cache accesses in this cache are either data memory access or instruction fetch as this is a system level cache.", + "MetricGroup": "LL_Cache_Effectiveness", + "ScaleUnit": "1per cache access" + }, + { + "MetricName": "ll_cache_read_miss_ratio", + "MetricExpr": "(LL_CACHE_MISS_RD / LL_CACHE_RD)", + "BriefDescription": "This metric measures the ratio of last level cache read accesses missed to the total number of last level cache accesses. This gives an indication of the effectiveness of the last level cache for read traffic. Note that cache accesses in this cache are either data memory access or instruction fetch as this is a system level cache.", + "MetricGroup": "Miss_Ratio;LL_Cache_Effectiveness", + "ScaleUnit": "1per cache access" + }, + { + "MetricName": "ll_cache_read_mpki", + "MetricExpr": "((LL_CACHE_MISS_RD / INST_RETIRED) * 1000)", + "BriefDescription": "This metric measures the number of last level cache read accesses missed per thousand instructions executed.", + "MetricGroup": "MPKI;LL_Cache_Effectiveness", + "ScaleUnit": "1MPKI" + }, + { + "MetricName": "load_percentage", + "MetricExpr": "((LD_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures load operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + }, + { + "ArchStdEvent": "retiring" + }, + { + "MetricName": "scalar_fp_percentage", + "MetricExpr": "((VFP_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures scalar floating point operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + }, + { + "MetricName": "simd_percentage", + "MetricExpr": "((ASE_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures advanced SIMD operations as a percentage of total operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + }, + { + "MetricName": "store_percentage", + "MetricExpr": "((ST_SPEC / INST_SPEC) * 100)", + "BriefDescription": "This metric measures store operations as a percentage of operations speculatively executed.", + "MetricGroup": "Operation_Mix", + "ScaleUnit": "1percent of operations" + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/pipeline.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/pipeline.json deleted file mode 100644 index f9fae15f7555..000000000000 --- a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/pipeline.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "ArchStdEvent": "STALL_FRONTEND" - }, - { - "ArchStdEvent": "STALL_BACKEND" - }, - { - "ArchStdEvent": "STALL" - }, - { - "ArchStdEvent": "STALL_SLOT_BACKEND" - }, - { - "ArchStdEvent": "STALL_SLOT_FRONTEND" - }, - { - "ArchStdEvent": "STALL_SLOT" - }, - { - "ArchStdEvent": "STALL_BACKEND_MEM" - } -] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/retired.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/retired.json new file mode 100644 index 000000000000..f297b049b62f --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/retired.json @@ -0,0 +1,30 @@ +[ + { + "ArchStdEvent": "SW_INCR", + "PublicDescription": "Counts software writes to the PMSWINC_EL0 (software PMU increment) register. The PMSWINC_EL0 register is a manually updated counter for use by application software.\n\nThis event could be used to measure any user program event, such as accesses to a particular data structure (by writing to the PMSWINC_EL0 register each time the data structure is accessed).\n\nTo use the PMSWINC_EL0 register and event, developers must insert instructions that write to the PMSWINC_EL0 register into the source code.\n\nSince the SW_INCR event records writes to the PMSWINC_EL0 register, there is no need to do a read/increment/write sequence to the PMSWINC_EL0 register." + }, + { + "ArchStdEvent": "INST_RETIRED", + "PublicDescription": "Counts instructions that have been architecturally executed." + }, + { + "ArchStdEvent": "CID_WRITE_RETIRED", + "PublicDescription": "Counts architecturally executed writes to the CONTEXTIDR register, which usually contain the kernel PID and can be output with hardware trace." + }, + { + "ArchStdEvent": "TTBR_WRITE_RETIRED", + "PublicDescription": "Counts architectural writes to TTBR0/1_EL1. If virtualization host extensions are enabled (by setting the HCR_EL2.E2H bit to 1), then accesses to TTBR0/1_EL1 that are redirected to TTBR0/1_EL2, or accesses to TTBR0/1_EL12, are counted. TTBRn registers are typically updated when the kernel is swapping user-space threads or applications." + }, + { + "ArchStdEvent": "BR_RETIRED", + "PublicDescription": "Counts architecturally executed branches, whether the branch is taken or not. Instructions that explicitly write to the PC are also counted." + }, + { + "ArchStdEvent": "BR_MIS_PRED_RETIRED", + "PublicDescription": "Counts branches counted by BR_RETIRED which were mispredicted and caused a pipeline flush." + }, + { + "ArchStdEvent": "OP_RETIRED", + "PublicDescription": "Counts micro-operations that are architecturally executed. This is a count of number of micro-operations retired from the commit queue in a single cycle." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spe.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spe.json new file mode 100644 index 000000000000..5de8b0f3a440 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spe.json @@ -0,0 +1,18 @@ +[ + { + "ArchStdEvent": "SAMPLE_POP", + "PublicDescription": "Counts statistical profiling sample population, the count of all operations that could be sampled but may or may not be chosen for sampling." + }, + { + "ArchStdEvent": "SAMPLE_FEED", + "PublicDescription": "Counts statistical profiling samples taken for sampling." + }, + { + "ArchStdEvent": "SAMPLE_FILTRATE", + "PublicDescription": "Counts statistical profiling samples taken which are not removed by filtering." + }, + { + "ArchStdEvent": "SAMPLE_COLLISION", + "PublicDescription": "Counts statistical profiling samples that have collided with a previous sample and so therefore not taken." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spec_operation.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spec_operation.json new file mode 100644 index 000000000000..1af961f8a6c8 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/spec_operation.json @@ -0,0 +1,110 @@ +[ + { + "ArchStdEvent": "BR_MIS_PRED", + "PublicDescription": "Counts branches which are speculatively executed and mispredicted." + }, + { + "ArchStdEvent": "BR_PRED", + "PublicDescription": "Counts branches speculatively executed and were predicted right." + }, + { + "ArchStdEvent": "INST_SPEC", + "PublicDescription": "Counts operations that have been speculatively executed." + }, + { + "ArchStdEvent": "OP_SPEC", + "PublicDescription": "Counts micro-operations speculatively executed. This is the count of the number of micro-operations dispatched in a cycle." + }, + { + "ArchStdEvent": "UNALIGNED_LD_SPEC", + "PublicDescription": "Counts unaligned memory read operations issued by the CPU. This event counts unaligned accesses (as defined by the actual instruction), even if they are subsequently issued as multiple aligned accesses. The event does not count preload operations (PLD, PLI)." + }, + { + "ArchStdEvent": "UNALIGNED_ST_SPEC", + "PublicDescription": "Counts unaligned memory write operations issued by the CPU. This event counts unaligned accesses (as defined by the actual instruction), even if they are subsequently issued as multiple aligned accesses." + }, + { + "ArchStdEvent": "UNALIGNED_LDST_SPEC", + "PublicDescription": "Counts unaligned memory operations issued by the CPU. This event counts unaligned accesses (as defined by the actual instruction), even if they are subsequently issued as multiple aligned accesses." + }, + { + "ArchStdEvent": "LDREX_SPEC", + "PublicDescription": "Counts Load-Exclusive operations that have been speculatively executed. Eg: LDREX, LDX" + }, + { + "ArchStdEvent": "STREX_PASS_SPEC", + "PublicDescription": "Counts store-exclusive operations that have been speculatively executed and have successfully completed the store operation." + }, + { + "ArchStdEvent": "STREX_FAIL_SPEC", + "PublicDescription": "Counts store-exclusive operations that have been speculatively executed and have not successfully completed the store operation." + }, + { + "ArchStdEvent": "STREX_SPEC", + "PublicDescription": "Counts store-exclusive operations that have been speculatively executed." + }, + { + "ArchStdEvent": "LD_SPEC", + "PublicDescription": "Counts speculatively executed load operations including Single Instruction Multiple Data (SIMD) load operations." + }, + { + "ArchStdEvent": "ST_SPEC", + "PublicDescription": "Counts speculatively executed store operations including Single Instruction Multiple Data (SIMD) store operations." + }, + { + "ArchStdEvent": "DP_SPEC", + "PublicDescription": "Counts speculatively executed logical or arithmetic instructions such as MOV/MVN operations." + }, + { + "ArchStdEvent": "ASE_SPEC", + "PublicDescription": "Counts speculatively executed Advanced SIMD operations excluding load, store and move micro-operations that move data to or from SIMD (vector) registers." + }, + { + "ArchStdEvent": "VFP_SPEC", + "PublicDescription": "Counts speculatively executed floating point operations. This event does not count operations that move data to or from floating point (vector) registers." + }, + { + "ArchStdEvent": "PC_WRITE_SPEC", + "PublicDescription": "Counts speculatively executed operations which cause software changes of the PC. Those operations include all taken branch operations." + }, + { + "ArchStdEvent": "CRYPTO_SPEC", + "PublicDescription": "Counts speculatively executed cryptographic operations except for PMULL and VMULL operations." + }, + { + "ArchStdEvent": "BR_IMMED_SPEC", + "PublicDescription": "Counts immediate branch operations which are speculatively executed." + }, + { + "ArchStdEvent": "BR_RETURN_SPEC", + "PublicDescription": "Counts procedure return operations (RET) which are speculatively executed." + }, + { + "ArchStdEvent": "BR_INDIRECT_SPEC", + "PublicDescription": "Counts indirect branch operations including procedure returns, which are speculatively executed. This includes operations that force a software change of the PC, other than exception-generating operations. Eg: BR Xn, RET" + }, + { + "ArchStdEvent": "ISB_SPEC", + "PublicDescription": "Counts ISB operations that are executed." + }, + { + "ArchStdEvent": "DSB_SPEC", + "PublicDescription": "Counts DSB operations that are speculatively issued to Load/Store unit in the CPU." + }, + { + "ArchStdEvent": "DMB_SPEC", + "PublicDescription": "Counts DMB operations that are speculatively issued to the Load/Store unit in the CPU. This event does not count implied barriers from load acquire/store release operations." + }, + { + "ArchStdEvent": "RC_LD_SPEC", + "PublicDescription": "Counts any load acquire operations that are speculatively executed. Eg: LDAR, LDARH, LDARB" + }, + { + "ArchStdEvent": "RC_ST_SPEC", + "PublicDescription": "Counts any store release operations that are speculatively executed. Eg: STLR, STLRH, STLRB'" + }, + { + "ArchStdEvent": "ASE_INST_SPEC", + "PublicDescription": "Counts speculatively executed Advanced SIMD operations." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/stall.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/stall.json new file mode 100644 index 000000000000..bbbebc805034 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/stall.json @@ -0,0 +1,30 @@ +[ + { + "ArchStdEvent": "STALL_FRONTEND", + "PublicDescription": "Counts cycles when frontend could not send any micro-operations to the rename stage because of frontend resource stalls caused by fetch memory latency or branch prediction flow stalls. All the frontend slots were empty during the cycle when this event counts." + }, + { + "ArchStdEvent": "STALL_BACKEND", + "PublicDescription": "Counts cycles whenever the rename unit is unable to send any micro-operations to the backend of the pipeline because of backend resource constraints. Backend resource constraints can include issue stage fullness, execution stage fullness, or other internal pipeline resource fullness. All the backend slots were empty during the cycle when this event counts." + }, + { + "ArchStdEvent": "STALL", + "PublicDescription": "Counts cycles when no operations are sent to the rename unit from the frontend or from the rename unit to the backend for any reason (either frontend or backend stall)." + }, + { + "ArchStdEvent": "STALL_SLOT_BACKEND", + "PublicDescription": "Counts slots per cycle in which no operations are sent from the rename unit to the backend due to backend resource constraints." + }, + { + "ArchStdEvent": "STALL_SLOT_FRONTEND", + "PublicDescription": "Counts slots per cycle in which no operations are sent to the rename unit from the frontend due to frontend resource constraints." + }, + { + "ArchStdEvent": "STALL_SLOT", + "PublicDescription": "Counts slots per cycle in which no operations are sent to the rename unit from the frontend or from the rename unit to the backend for any reason (either frontend or backend stall)." + }, + { + "ArchStdEvent": "STALL_BACKEND_MEM", + "PublicDescription": "Counts cycles when the backend is stalled because there is a pending demand load request in progress in the last level core cache." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/sve.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/sve.json new file mode 100644 index 000000000000..5137e2075a76 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/sve.json @@ -0,0 +1,30 @@ +[ + { + "ArchStdEvent": "SVE_INST_SPEC", + "PublicDescription": "Counts speculatively executed operations that are SVE operations." + }, + { + "ArchStdEvent": "SVE_PRED_SPEC", + "PublicDescription": "Counts speculatively executed predicated SVE operations." + }, + { + "ArchStdEvent": "SVE_PRED_EMPTY_SPEC", + "PublicDescription": "Counts speculatively executed predicated SVE operations with no active predicate elements." + }, + { + "ArchStdEvent": "SVE_PRED_FULL_SPEC", + "PublicDescription": "Counts speculatively executed predicated SVE operations with all predicate elements active." + }, + { + "ArchStdEvent": "SVE_PRED_PARTIAL_SPEC", + "PublicDescription": "Counts speculatively executed predicated SVE operations with at least one but not all active predicate elements." + }, + { + "ArchStdEvent": "SVE_LDFF_SPEC", + "PublicDescription": "Counts speculatively executed SVE first fault or non-fault load operations." + }, + { + "ArchStdEvent": "SVE_LDFF_FAULT_SPEC", + "PublicDescription": "Counts speculatively executed SVE first fault or non-fault load operations that clear at least one bit in the FFR." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/tlb.json b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/tlb.json new file mode 100644 index 000000000000..b550af1831f5 --- /dev/null +++ b/tools/perf/pmu-events/arch/arm64/arm/neoverse-v1/tlb.json @@ -0,0 +1,66 @@ +[ + { + "ArchStdEvent": "L1I_TLB_REFILL", + "PublicDescription": "Counts level 1 instruction TLB refills from any Instruction fetch. If there are multiple misses in the TLB that are resolved by the refill, then this event only counts once. This event will not count if the translation table walk results in a fault (such as a translation or access fault), since there is no new translation created for the TLB." + }, + { + "ArchStdEvent": "L1D_TLB_REFILL", + "PublicDescription": "Counts level 1 data TLB accesses that resulted in TLB refills. If there are multiple misses in the TLB that are resolved by the refill, then this event only counts once. This event counts for refills caused by preload instructions or hardware prefetch accesses. This event counts regardless of whether the miss hits in L2 or results in a translation table walk. This event will not count if the translation table walk results in a fault (such as a translation or access fault), since there is no new translation created for the TLB. This event will not count on an access from an AT(address translation) instruction." + }, + { + "ArchStdEvent": "L1D_TLB", + "PublicDescription": "Counts level 1 data TLB accesses caused by any memory load or store operation. Note that load or store instructions can be broken up into multiple memory operations. This event does not count TLB maintenance operations." + }, + { + "ArchStdEvent": "L1I_TLB", + "PublicDescription": "Counts level 1 instruction TLB accesses, whether the access hits or misses in the TLB. This event counts both demand accesses and prefetch or preload generated accesses." + }, + { + "ArchStdEvent": "L2D_TLB_REFILL", + "PublicDescription": "Counts level 2 TLB refills caused by memory operations from both data and instruction fetch, except for those caused by TLB maintenance operations and hardware prefetches." + }, + { + "ArchStdEvent": "L2D_TLB", + "PublicDescription": "Counts level 2 TLB accesses except those caused by TLB maintenance operations." + }, + { + "ArchStdEvent": "DTLB_WALK", + "PublicDescription": "Counts data memory translation table walks caused by a miss in the L2 TLB driven by a memory access. Note that partial translations that also cause a table walk are counted. This event does not count table walks caused by TLB maintenance operations." + }, + { + "ArchStdEvent": "ITLB_WALK", + "PublicDescription": "Counts instruction memory translation table walks caused by a miss in the L2 TLB driven by a memory access. Partial translations that also cause a table walk are counted. This event does not count table walks caused by TLB maintenance operations." + }, + { + "ArchStdEvent": "L1D_TLB_REFILL_RD", + "PublicDescription": "Counts level 1 data TLB refills caused by memory read operations. If there are multiple misses in the TLB that are resolved by the refill, then this event only counts once. This event counts for refills caused by preload instructions or hardware prefetch accesses. This event counts regardless of whether the miss hits in L2 or results in a translation table walk. This event will not count if the translation table walk results in a fault (such as a translation or access fault), since there is no new translation created for the TLB. This event will not count on an access from an Address Translation (AT) instruction." + }, + { + "ArchStdEvent": "L1D_TLB_REFILL_WR", + "PublicDescription": "Counts level 1 data TLB refills caused by data side memory write operations. If there are multiple misses in the TLB that are resolved by the refill, then this event only counts once. This event counts for refills caused by preload instructions or hardware prefetch accesses. This event counts regardless of whether the miss hits in L2 or results in a translation table walk. This event will not count if the table walk results in a fault (such as a translation or access fault), since there is no new translation created for the TLB. This event will not count with an access from an Address Translation (AT) instruction." + }, + { + "ArchStdEvent": "L1D_TLB_RD", + "PublicDescription": "Counts level 1 data TLB accesses caused by memory read operations. This event counts whether the access hits or misses in the TLB. This event does not count TLB maintenance operations." + }, + { + "ArchStdEvent": "L1D_TLB_WR", + "PublicDescription": "Counts any L1 data side TLB accesses caused by memory write operations. This event counts whether the access hits or misses in the TLB. This event does not count TLB maintenance operations." + }, + { + "ArchStdEvent": "L2D_TLB_REFILL_RD", + "PublicDescription": "Counts level 2 TLB refills caused by memory read operations from both data and instruction fetch except for those caused by TLB maintenance operations or hardware prefetches." + }, + { + "ArchStdEvent": "L2D_TLB_REFILL_WR", + "PublicDescription": "Counts level 2 TLB refills caused by memory write operations from both data and instruction fetch except for those caused by TLB maintenance operations." + }, + { + "ArchStdEvent": "L2D_TLB_RD", + "PublicDescription": "Counts level 2 TLB accesses caused by memory read operations from both data and instruction fetch except for those caused by TLB maintenance operations." + }, + { + "ArchStdEvent": "L2D_TLB_WR", + "PublicDescription": "Counts level 2 TLB accesses caused by memory write operations from both data and instruction fetch except for those caused by TLB maintenance operations." + } +] diff --git a/tools/perf/pmu-events/arch/arm64/mapfile.csv b/tools/perf/pmu-events/arch/arm64/mapfile.csv index 32674ddd2b63..5b58db5032c1 100644 --- a/tools/perf/pmu-events/arch/arm64/mapfile.csv +++ b/tools/perf/pmu-events/arch/arm64/mapfile.csv @@ -4,7 +4,7 @@ # where # MIDR Processor version # Variant[23:20] and Revision [3:0] should be zero. -# Version could be used to track version of of JSON file +# Version could be used to track version of JSON file # but currently unused. # JSON/file/pathname is the path to JSON file, relative # to tools/perf/pmu-events/arch/arm64/. diff --git a/tools/perf/pmu-events/arch/nds32/mapfile.csv b/tools/perf/pmu-events/arch/nds32/mapfile.csv index efb395f26883..c76e5fbdac23 100644 --- a/tools/perf/pmu-events/arch/nds32/mapfile.csv +++ b/tools/perf/pmu-events/arch/nds32/mapfile.csv @@ -4,7 +4,7 @@ # where # MIDR Processor version # Variant[23:20] and Revision [3:0] should be zero. -# Version could be used to track version of of JSON file +# Version could be used to track version of JSON file # but currently unused. # JSON/file/pathname is the path to JSON file, relative # to tools/perf/pmu-events/arch/arm64/. diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv b/tools/perf/pmu-events/arch/powerpc/mapfile.csv index 4abdfc3f9692..f4908af7ad66 100644 --- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv +++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv @@ -3,7 +3,7 @@ # # where # PVR Processor version -# Version could be used to track version of of JSON file +# Version could be used to track version of JSON file # but currently unused. # JSON/file/pathname is the path to JSON file, relative # to tools/perf/pmu-events/arch/powerpc/. @@ -13,6 +13,6 @@ # # Power8 entries -004[bcd][[:xdigit:]]{4},1,power8,core -004e[[:xdigit:]]{4},1,power9,core -0080[[:xdigit:]]{4},1,power10,core +0x004[bcd][[:xdigit:]]{4},1,power8,core +0x004e[[:xdigit:]]{4},1,power9,core +0x0080[[:xdigit:]]{4},1,power10,core diff --git a/tools/perf/pmu-events/arch/powerpc/power10/datasource.json b/tools/perf/pmu-events/arch/powerpc/power10/datasource.json new file mode 100644 index 000000000000..6b0356f2d301 --- /dev/null +++ b/tools/perf/pmu-events/arch/powerpc/power10/datasource.json @@ -0,0 +1,1787 @@ +[ + { + "EventCode": "0x200FE", + "EventName": "PM_DATA_FROM_L2MISS", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x300FE", + "EventName": "PM_DATA_FROM_L3MISS", + "BriefDescription": "The processor's L1 data cache was reloaded from beyond the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x400FE", + "EventName": "PM_DATA_FROM_MEMORY", + "BriefDescription": "The processor's data cache was reloaded from local, remote, or distant memory due to a demand miss." + }, + { + "EventCode": "0x000300000000C040", + "EventName": "PM_INST_FROM_L2", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x000340000000C040", + "EventName": "PM_DATA_FROM_L2", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x000300000010C040", + "EventName": "PM_INST_FROM_L2_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x000340000020C040", + "EventName": "PM_DATA_FROM_L2_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x003F00000000C040", + "EventName": "PM_INST_FROM_L1MISS", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L1 due to a demand miss." + }, + { + "EventCode": "0x003F40000000C040", + "EventName": "PM_DATA_FROM_L1MISS", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L1 due to a demand miss." + }, + { + "EventCode": "0x003F00000010C040", + "EventName": "PM_INST_FROM_L1MISS_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L1 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x003F40000020C040", + "EventName": "PM_DATA_FROM_L1MISS_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L1 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x000040000000C040", + "EventName": "PM_DATA_FROM_L2_NO_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x000040000020C040", + "EventName": "PM_DATA_FROM_L2_NO_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x004040000000C040", + "EventName": "PM_DATA_FROM_L2_MEPF", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x004040000020C040", + "EventName": "PM_DATA_FROM_L2_MEPF_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x008040000000C040", + "EventName": "PM_DATA_FROM_L2_LDHITST_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict on ld-hit-store from the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x008040000020C040", + "EventName": "PM_DATA_FROM_L2_LDHITST_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict on ld-hit-store from the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x00C040000000C040", + "EventName": "PM_DATA_FROM_L2_OTHER_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict other than ld-hit-store from the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x00C040000020C040", + "EventName": "PM_DATA_FROM_L2_OTHER_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict other than ld-hit-store from the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x000380000000C040", + "EventName": "PM_INST_FROM_L2MISS", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L2 due to a demand miss." + }, + { + "EventCode": "0x000380000010C040", + "EventName": "PM_INST_FROM_L2MISS_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0003C0000020C040", + "EventName": "PM_DATA_FROM_L2MISS_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L2 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x010300000000C040", + "EventName": "PM_INST_FROM_L3", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x010340000000C040", + "EventName": "PM_DATA_FROM_L3", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x010300000010C040", + "EventName": "PM_INST_FROM_L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x010340000020C040", + "EventName": "PM_DATA_FROM_L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x010040000000C040", + "EventName": "PM_DATA_FROM_L3_NO_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x010040000020C040", + "EventName": "PM_DATA_FROM_L3_NO_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x014040000000C040", + "EventName": "PM_DATA_FROM_L3_MEPF", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x014040000020C040", + "EventName": "PM_DATA_FROM_L3_MEPF_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x01C040000000C040", + "EventName": "PM_DATA_FROM_L3_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x01C040000020C040", + "EventName": "PM_DATA_FROM_L3_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x000780000000C040", + "EventName": "PM_INST_FROM_L3MISS", + "BriefDescription": "The processor's instruction cache was reloaded from beyond the local core's L3 due to a demand miss." + }, + { + "EventCode": "0x000780000010C040", + "EventName": "PM_INST_FROM_L3MISS_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from beyond the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0007C0000020C040", + "EventName": "PM_DATA_FROM_L3MISS_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from beyond the local core's L3 due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080040000000C040", + "EventName": "PM_DATA_FROM_L21_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x080040000020C040", + "EventName": "PM_DATA_FROM_L21_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x084040000000C040", + "EventName": "PM_DATA_FROM_L21_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x084040000020C040", + "EventName": "PM_DATA_FROM_L21_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080100000000C040", + "EventName": "PM_INST_FROM_L21_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x080140000000C040", + "EventName": "PM_DATA_FROM_L21_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x080100000010C040", + "EventName": "PM_INST_FROM_L21_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080140000020C040", + "EventName": "PM_DATA_FROM_L21_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x088040000000C040", + "EventName": "PM_DATA_FROM_L31_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x088040000020C040", + "EventName": "PM_DATA_FROM_L31_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x08C040000000C040", + "EventName": "PM_DATA_FROM_L31_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x08C040000020C040", + "EventName": "PM_DATA_FROM_L31_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x088100000000C040", + "EventName": "PM_INST_FROM_L31_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x088140000000C040", + "EventName": "PM_DATA_FROM_L31_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x088100000010C040", + "EventName": "PM_INST_FROM_L31_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x088140000020C040", + "EventName": "PM_DATA_FROM_L31_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080240000000C040", + "EventName": "PM_DATA_FROM_REGENT_L2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x080240000020C040", + "EventName": "PM_DATA_FROM_REGENT_L2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x084240000000C040", + "EventName": "PM_DATA_FROM_REGENT_L2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x084240000020C040", + "EventName": "PM_DATA_FROM_REGENT_L2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080300000000C040", + "EventName": "PM_INST_FROM_REGENT_L2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x080340000000C040", + "EventName": "PM_DATA_FROM_REGENT_L2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss." + }, + { + "EventCode": "0x080300000010C040", + "EventName": "PM_INST_FROM_REGENT_L2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080340000020C040", + "EventName": "PM_DATA_FROM_REGENT_L2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A0040000000C040", + "EventName": "PM_DATA_FROM_L21_NON_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A0040000020C040", + "EventName": "PM_DATA_FROM_L21_NON_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A4040000000C040", + "EventName": "PM_DATA_FROM_L21_NON_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A4040000020C040", + "EventName": "PM_DATA_FROM_L21_NON_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A0100000000C040", + "EventName": "PM_INST_FROM_L21_NON_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A0140000000C040", + "EventName": "PM_DATA_FROM_L21_NON_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A0100000010C040", + "EventName": "PM_INST_FROM_L21_NON_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A0140000020C040", + "EventName": "PM_DATA_FROM_L21_NON_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A8040000000C040", + "EventName": "PM_DATA_FROM_L31_NON_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A8040000020C040", + "EventName": "PM_DATA_FROM_L31_NON_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0AC040000000C040", + "EventName": "PM_DATA_FROM_L31_NON_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0AC040000020C040", + "EventName": "PM_DATA_FROM_L31_NON_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A8100000000C040", + "EventName": "PM_INST_FROM_L31_NON_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A8140000000C040", + "EventName": "PM_DATA_FROM_L31_NON_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A8100000010C040", + "EventName": "PM_INST_FROM_L31_NON_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A8140000020C040", + "EventName": "PM_DATA_FROM_L31_NON_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A0240000000C040", + "EventName": "PM_DATA_FROM_NON_REGENT_L2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A0240000020C040", + "EventName": "PM_DATA_FROM_NON_REGENT_L2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A4240000000C040", + "EventName": "PM_DATA_FROM_NON_REGENT_L2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A4240000020C040", + "EventName": "PM_DATA_FROM_NON_REGENT_L2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A0300000000C040", + "EventName": "PM_INST_FROM_NON_REGENT_L2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A0340000000C040", + "EventName": "PM_DATA_FROM_NON_REGENT_L2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss." + }, + { + "EventCode": "0x0A0300000010C040", + "EventName": "PM_INST_FROM_NON_REGENT_L2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0A0340000020C040", + "EventName": "PM_DATA_FROM_NON_REGENT_L2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x094100000000C040", + "EventName": "PM_INST_FROM_LMEM", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's memory due to a demand miss." + }, + { + "EventCode": "0x094040000000C040", + "EventName": "PM_DATA_FROM_LMEM", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's memory due to a demand miss." + }, + { + "EventCode": "0x094100000010C040", + "EventName": "PM_INST_FROM_LMEM_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x094040000020C040", + "EventName": "PM_DATA_FROM_LMEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x098040000000C040", + "EventName": "PM_DATA_FROM_L_OC_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache due to a demand miss." + }, + { + "EventCode": "0x098040000020C040", + "EventName": "PM_DATA_FROM_L_OC_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x09C040000000C040", + "EventName": "PM_DATA_FROM_L_OC_MEM", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI memory due to a demand miss." + }, + { + "EventCode": "0x09C040000020C040", + "EventName": "PM_DATA_FROM_L_OC_MEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x098100000000C040", + "EventName": "PM_INST_FROM_L_OC_ANY", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss." + }, + { + "EventCode": "0x098140000000C040", + "EventName": "PM_DATA_FROM_L_OC_ANY", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss." + }, + { + "EventCode": "0x098100000010C040", + "EventName": "PM_INST_FROM_L_OC_ANY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x098140000020C040", + "EventName": "PM_DATA_FROM_L_OC_ANY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0040000000C040", + "EventName": "PM_DATA_FROM_RL2_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C0040000020C040", + "EventName": "PM_DATA_FROM_RL2_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C4040000000C040", + "EventName": "PM_DATA_FROM_RL2_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C4040000020C040", + "EventName": "PM_DATA_FROM_RL2_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0100000000C040", + "EventName": "PM_INST_FROM_RL2", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C0140000000C040", + "EventName": "PM_DATA_FROM_RL2", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C0100000010C040", + "EventName": "PM_INST_FROM_RL2_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0140000020C040", + "EventName": "PM_DATA_FROM_RL2_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C8040000000C040", + "EventName": "PM_DATA_FROM_RL3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C8040000020C040", + "EventName": "PM_DATA_FROM_RL3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0CC040000000C040", + "EventName": "PM_DATA_FROM_RL3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0CC040000020C040", + "EventName": "PM_DATA_FROM_RL3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C8100000000C040", + "EventName": "PM_INST_FROM_RL3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C8140000000C040", + "EventName": "PM_DATA_FROM_RL3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C8100000010C040", + "EventName": "PM_INST_FROM_RL3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C8140000020C040", + "EventName": "PM_DATA_FROM_RL3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0240000000C040", + "EventName": "PM_DATA_FROM_RL2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C0240000020C040", + "EventName": "PM_DATA_FROM_RL2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C4240000000C040", + "EventName": "PM_DATA_FROM_RL2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C4240000020C040", + "EventName": "PM_DATA_FROM_RL2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0300000000C040", + "EventName": "PM_INST_FROM_RL2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C0340000000C040", + "EventName": "PM_DATA_FROM_RL2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss." + }, + { + "EventCode": "0x0C0300000010C040", + "EventName": "PM_INST_FROM_RL2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0340000020C040", + "EventName": "PM_DATA_FROM_RL2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0D4100000000C040", + "EventName": "PM_INST_FROM_RMEM", + "BriefDescription": "The processor's instruction cache was reloaded from remote memory (MC slow) due to a demand miss." + }, + { + "EventCode": "0x0D4040000000C040", + "EventName": "PM_DATA_FROM_RMEM", + "BriefDescription": "The processor's L1 data cache was reloaded from remote memory (MC slow) due to a demand miss." + }, + { + "EventCode": "0x0D4100000010C040", + "EventName": "PM_INST_FROM_RMEM_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from remote memory (MC slow) due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0D4040000020C040", + "EventName": "PM_DATA_FROM_RMEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from remote memory (MC slow) due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0D8040000000C040", + "EventName": "PM_DATA_FROM_R_OC_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache due to a demand miss." + }, + { + "EventCode": "0x0D8040000020C040", + "EventName": "PM_DATA_FROM_R_OC_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0DC040000000C040", + "EventName": "PM_DATA_FROM_R_OC_MEM", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI memory due to a demand miss." + }, + { + "EventCode": "0x0DC040000020C040", + "EventName": "PM_DATA_FROM_R_OC_MEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0D8100000000C040", + "EventName": "PM_INST_FROM_R_OC_ANY", + "BriefDescription": "The processor's instruction cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss." + }, + { + "EventCode": "0x0D8140000000C040", + "EventName": "PM_DATA_FROM_R_OC_ANY", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss." + }, + { + "EventCode": "0x0D8100000010C040", + "EventName": "PM_INST_FROM_R_OC_ANY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0D8140000020C040", + "EventName": "PM_DATA_FROM_R_OC_ANY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E0040000000C040", + "EventName": "PM_DATA_FROM_DL2_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E0040000020C040", + "EventName": "PM_DATA_FROM_DL2_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E4040000000C040", + "EventName": "PM_DATA_FROM_DL2_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E4040000020C040", + "EventName": "PM_DATA_FROM_DL2_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E0100000000C040", + "EventName": "PM_INST_FROM_DL2", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E0140000000C040", + "EventName": "PM_DATA_FROM_DL2", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E0100000010C040", + "EventName": "PM_INST_FROM_DL2_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E0140000020C040", + "EventName": "PM_DATA_FROM_DL2_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E8040000000C040", + "EventName": "PM_DATA_FROM_DL3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E8040000020C040", + "EventName": "PM_DATA_FROM_DL3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0EC040000000C040", + "EventName": "PM_DATA_FROM_DL3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0EC040000020C040", + "EventName": "PM_DATA_FROM_DL3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E8100000000C040", + "EventName": "PM_INST_FROM_DL3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E8140000000C040", + "EventName": "PM_DATA_FROM_DL3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E8100000010C040", + "EventName": "PM_INST_FROM_DL3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E8140000020C040", + "EventName": "PM_DATA_FROM_DL3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E0240000000C040", + "EventName": "PM_DATA_FROM_DL2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E0240000020C040", + "EventName": "PM_DATA_FROM_DL2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E4240000000C040", + "EventName": "PM_DATA_FROM_DL2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E4240000020C040", + "EventName": "PM_DATA_FROM_DL2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E0300000000C040", + "EventName": "PM_INST_FROM_DL2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E0340000000C040", + "EventName": "PM_DATA_FROM_DL2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss." + }, + { + "EventCode": "0x0E0300000010C040", + "EventName": "PM_INST_FROM_DL2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0E0340000020C040", + "EventName": "PM_DATA_FROM_DL2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0F4100000000C040", + "EventName": "PM_INST_FROM_DMEM", + "BriefDescription": "The processor's instruction cache was reloaded from distant memory (MC slow) due to a demand miss." + }, + { + "EventCode": "0x0F4040000000C040", + "EventName": "PM_DATA_FROM_DMEM", + "BriefDescription": "The processor's L1 data cache was reloaded from distant memory (MC slow) due to a demand miss." + }, + { + "EventCode": "0x0F4100000010C040", + "EventName": "PM_INST_FROM_DMEM_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from distant memory (MC slow) due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0F4040000020C040", + "EventName": "PM_DATA_FROM_DMEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from distant memory (MC slow) due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0F8040000000C040", + "EventName": "PM_DATA_FROM_D_OC_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache due to a demand miss." + }, + { + "EventCode": "0x0F8040000020C040", + "EventName": "PM_DATA_FROM_D_OC_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0FC040000000C040", + "EventName": "PM_DATA_FROM_D_OC_MEM", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI memory due to a demand miss." + }, + { + "EventCode": "0x0FC040000020C040", + "EventName": "PM_DATA_FROM_D_OC_MEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0F8100000000C040", + "EventName": "PM_INST_FROM_D_OC_ANY", + "BriefDescription": "The processor's instruction cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss." + }, + { + "EventCode": "0x0F8140000000C040", + "EventName": "PM_DATA_FROM_D_OC_ANY", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss." + }, + { + "EventCode": "0x0F8100000010C040", + "EventName": "PM_INST_FROM_D_OC_ANY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0F8140000020C040", + "EventName": "PM_DATA_FROM_D_OC_ANY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080B00000000C040", + "EventName": "PM_INST_FROM_ONCHIP_CACHE", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss." + }, + { + "EventCode": "0x080B40000000C040", + "EventName": "PM_DATA_FROM_ONCHIP_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss." + }, + { + "EventCode": "0x080B00000010C040", + "EventName": "PM_INST_FROM_ONCHIP_CACHE_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x080B40000020C040", + "EventName": "PM_DATA_FROM_ONCHIP_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0B00000000C040", + "EventName": "PM_INST_FROM_OFFCHIP_CACHE", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss." + }, + { + "EventCode": "0x0C0B40000000C040", + "EventName": "PM_DATA_FROM_OFFCHIP_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss." + }, + { + "EventCode": "0x0C0B00000010C040", + "EventName": "PM_INST_FROM_OFFCHIP_CACHE_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x0C0B40000020C040", + "EventName": "PM_DATA_FROM_OFFCHIP_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x095900000000C040", + "EventName": "PM_INST_FROM_ANY_MEMORY", + "BriefDescription": "The processor's instruction cache was reloaded from any chip's memory (MC slow) due to a demand miss." + }, + { + "EventCode": "0x095840000000C040", + "EventName": "PM_DATA_FROM_ANY_MEMORY", + "BriefDescription": "The processor's L1 data cache was reloaded from any chip's memory (MC slow) due to a demand miss." + }, + { + "EventCode": "0x095900000010C040", + "EventName": "PM_INST_FROM_ANY_MEMORY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from any chip's memory (MC slow) due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x095840000020C040", + "EventName": "PM_DATA_FROM_ANY_MEMORY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from any chip's memory (MC slow) due to a demand miss or prefetch reload." + }, + { + "EventCode": "0x000300000000C142", + "EventName": "PM_MRK_INST_FROM_L2", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x000340000000C142", + "EventName": "PM_MRK_DATA_FROM_L2", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x000300000010C142", + "EventName": "PM_MRK_INST_FROM_L2_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x000340000020C142", + "EventName": "PM_MRK_DATA_FROM_L2_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x003F00000000C142", + "EventName": "PM_MRK_INST_FROM_L1MISS", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L1 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x003F40000000C142", + "EventName": "PM_MRK_DATA_FROM_L1MISS", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L1 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x003F00000010C142", + "EventName": "PM_MRK_INST_FROM_L1MISS_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L1 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x003F40000020C142", + "EventName": "PM_MRK_DATA_FROM_L1MISS_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L1 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x000040000000C142", + "EventName": "PM_MRK_DATA_FROM_L2_NO_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x000040000020C142", + "EventName": "PM_MRK_DATA_FROM_L2_NO_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x004040000000C142", + "EventName": "PM_MRK_DATA_FROM_L2_MEPF", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x004040000020C142", + "EventName": "PM_MRK_DATA_FROM_L2_MEPF_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x008040000000C142", + "EventName": "PM_MRK_DATA_FROM_L2_LDHITST_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict on ld-hit-store from the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x008040000020C142", + "EventName": "PM_MRK_DATA_FROM_L2_LDHITST_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict on ld-hit-store from the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x00C040000000C142", + "EventName": "PM_MRK_DATA_FROM_L2_OTHER_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict other than ld-hit-store from the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x00C040000020C142", + "EventName": "PM_MRK_DATA_FROM_L2_OTHER_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data that had a dispatch conflict other than ld-hit-store from the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x000380000000C142", + "EventName": "PM_MRK_INST_FROM_L2MISS", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0003C0000000C142", + "EventName": "PM_MRK_DATA_FROM_L2MISS", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L2 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x000380000010C142", + "EventName": "PM_MRK_INST_FROM_L2MISS_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a source beyond the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0003C0000020C142", + "EventName": "PM_MRK_DATA_FROM_L2MISS_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L2 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x010300000000C142", + "EventName": "PM_MRK_INST_FROM_L3", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x010340000000C142", + "EventName": "PM_MRK_DATA_FROM_L3", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x010300000010C142", + "EventName": "PM_MRK_INST_FROM_L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x010340000020C142", + "EventName": "PM_MRK_DATA_FROM_L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x010040000000C142", + "EventName": "PM_MRK_DATA_FROM_L3_NO_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x010040000020C142", + "EventName": "PM_MRK_DATA_FROM_L3_NO_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded without dispatch conflicts with data NOT in the MEPF state from the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x014040000000C142", + "EventName": "PM_MRK_DATA_FROM_L3_MEPF", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x014040000020C142", + "EventName": "PM_MRK_DATA_FROM_L3_MEPF_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with data in the MEPF state without dispatch conflicts from the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x01C040000000C142", + "EventName": "PM_MRK_DATA_FROM_L3_CONFLICT", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x01C040000020C142", + "EventName": "PM_MRK_DATA_FROM_L3_CONFLICT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x000780000000C142", + "EventName": "PM_MRK_INST_FROM_L3MISS", + "BriefDescription": "The processor's instruction cache was reloaded from beyond the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0007C0000000C142", + "EventName": "PM_MRK_DATA_FROM_L3MISS", + "BriefDescription": "The processor's L1 data cache was reloaded from beyond the local core's L3 due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x000780000010C142", + "EventName": "PM_MRK_INST_FROM_L3MISS_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from beyond the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0007C0000020C142", + "EventName": "PM_MRK_DATA_FROM_L3MISS_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from beyond the local core's L3 due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080040000000C142", + "EventName": "PM_MRK_DATA_FROM_L21_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080040000020C142", + "EventName": "PM_MRK_DATA_FROM_L21_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x084040000000C142", + "EventName": "PM_MRK_DATA_FROM_L21_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x084040000020C142", + "EventName": "PM_MRK_DATA_FROM_L21_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080100000000C142", + "EventName": "PM_MRK_INST_FROM_L21_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080140000000C142", + "EventName": "PM_MRK_DATA_FROM_L21_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080100000010C142", + "EventName": "PM_MRK_INST_FROM_L21_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080140000020C142", + "EventName": "PM_MRK_DATA_FROM_L21_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x088040000000C142", + "EventName": "PM_MRK_DATA_FROM_L31_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x088040000020C142", + "EventName": "PM_MRK_DATA_FROM_L31_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x08C040000000C142", + "EventName": "PM_MRK_DATA_FROM_L31_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x08C040000020C142", + "EventName": "PM_MRK_DATA_FROM_L31_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x088100000000C142", + "EventName": "PM_MRK_INST_FROM_L31_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x088140000000C142", + "EventName": "PM_MRK_DATA_FROM_L31_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x088100000010C142", + "EventName": "PM_MRK_INST_FROM_L31_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x088140000020C142", + "EventName": "PM_MRK_DATA_FROM_L31_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080240000000C142", + "EventName": "PM_MRK_DATA_FROM_REGENT_L2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080240000020C142", + "EventName": "PM_MRK_DATA_FROM_REGENT_L2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x084240000000C142", + "EventName": "PM_MRK_DATA_FROM_REGENT_L2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x084240000020C142", + "EventName": "PM_MRK_DATA_FROM_REGENT_L2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080300000000C142", + "EventName": "PM_MRK_INST_FROM_REGENT_L2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080340000000C142", + "EventName": "PM_MRK_DATA_FROM_REGENT_L2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080300000010C142", + "EventName": "PM_MRK_INST_FROM_REGENT_L2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080340000020C142", + "EventName": "PM_MRK_DATA_FROM_REGENT_L2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in the same regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A0040000000C142", + "EventName": "PM_MRK_DATA_FROM_L21_NON_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A0040000020C142", + "EventName": "PM_MRK_DATA_FROM_L21_NON_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A4040000000C142", + "EventName": "PM_MRK_DATA_FROM_L21_NON_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A4040000020C142", + "EventName": "PM_MRK_DATA_FROM_L21_NON_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A0100000000C142", + "EventName": "PM_MRK_INST_FROM_L21_NON_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A0140000000C142", + "EventName": "PM_MRK_DATA_FROM_L21_NON_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A0100000010C142", + "EventName": "PM_MRK_INST_FROM_L21_NON_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A0140000020C142", + "EventName": "PM_MRK_DATA_FROM_L21_NON_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A8040000000C142", + "EventName": "PM_MRK_DATA_FROM_L31_NON_REGENT_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A8040000020C142", + "EventName": "PM_MRK_DATA_FROM_L31_NON_REGENT_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0AC040000000C142", + "EventName": "PM_MRK_DATA_FROM_L31_NON_REGENT_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0AC040000020C142", + "EventName": "PM_MRK_DATA_FROM_L31_NON_REGENT_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A8100000000C142", + "EventName": "PM_MRK_INST_FROM_L31_NON_REGENT", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A8140000000C142", + "EventName": "PM_MRK_DATA_FROM_L31_NON_REGENT", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A8100000010C142", + "EventName": "PM_MRK_INST_FROM_L31_NON_REGENT_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A8140000020C142", + "EventName": "PM_MRK_DATA_FROM_L31_NON_REGENT_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A0240000000C142", + "EventName": "PM_MRK_DATA_FROM_NON_REGENT_L2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A0240000020C142", + "EventName": "PM_MRK_DATA_FROM_NON_REGENT_L2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A4240000000C142", + "EventName": "PM_MRK_DATA_FROM_NON_REGENT_L2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A4240000020C142", + "EventName": "PM_MRK_DATA_FROM_NON_REGENT_L2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A0300000000C142", + "EventName": "PM_MRK_INST_FROM_NON_REGENT_L2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A0340000000C142", + "EventName": "PM_MRK_DATA_FROM_NON_REGENT_L2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0A0300000010C142", + "EventName": "PM_MRK_INST_FROM_NON_REGENT_L2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0A0340000020C142", + "EventName": "PM_MRK_DATA_FROM_NON_REGENT_L2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 on the same chip in a different regent due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x094100000000C142", + "EventName": "PM_MRK_INST_FROM_LMEM", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x094040000000C142", + "EventName": "PM_MRK_DATA_FROM_LMEM", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x094100000010C142", + "EventName": "PM_MRK_INST_FROM_LMEM_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x094040000020C142", + "EventName": "PM_MRK_DATA_FROM_LMEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x098040000000C142", + "EventName": "PM_MRK_DATA_FROM_L_OC_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x098040000020C142", + "EventName": "PM_MRK_DATA_FROM_L_OC_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x09C040000000C142", + "EventName": "PM_MRK_DATA_FROM_L_OC_MEM", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x09C040000020C142", + "EventName": "PM_MRK_DATA_FROM_L_OC_MEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x098100000000C142", + "EventName": "PM_MRK_INST_FROM_L_OC_ANY", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x098140000000C142", + "EventName": "PM_MRK_DATA_FROM_L_OC_ANY", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x098100000010C142", + "EventName": "PM_MRK_INST_FROM_L_OC_ANY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x098140000020C142", + "EventName": "PM_MRK_DATA_FROM_L_OC_ANY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from the local chip's OpenCAPI cache or memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0040000000C142", + "EventName": "PM_MRK_DATA_FROM_RL2_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0040000020C142", + "EventName": "PM_MRK_DATA_FROM_RL2_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C4040000000C142", + "EventName": "PM_MRK_DATA_FROM_RL2_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C4040000020C142", + "EventName": "PM_MRK_DATA_FROM_RL2_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0100000000C142", + "EventName": "PM_MRK_INST_FROM_RL2", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0140000000C142", + "EventName": "PM_MRK_DATA_FROM_RL2", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0100000010C142", + "EventName": "PM_MRK_INST_FROM_RL2_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0140000020C142", + "EventName": "PM_MRK_DATA_FROM_RL2_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C8040000000C142", + "EventName": "PM_MRK_DATA_FROM_RL3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C8040000020C142", + "EventName": "PM_MRK_DATA_FROM_RL3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0CC040000000C142", + "EventName": "PM_MRK_DATA_FROM_RL3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0CC040000020C142", + "EventName": "PM_MRK_DATA_FROM_RL3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C8100000000C142", + "EventName": "PM_MRK_INST_FROM_RL3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C8140000000C142", + "EventName": "PM_MRK_DATA_FROM_RL3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C8100000010C142", + "EventName": "PM_MRK_INST_FROM_RL3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C8140000020C142", + "EventName": "PM_MRK_DATA_FROM_RL3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0240000000C142", + "EventName": "PM_MRK_DATA_FROM_RL2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0240000020C142", + "EventName": "PM_MRK_DATA_FROM_RL2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C4240000000C142", + "EventName": "PM_MRK_DATA_FROM_RL2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C4240000020C142", + "EventName": "PM_MRK_DATA_FROM_RL2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0300000000C142", + "EventName": "PM_MRK_INST_FROM_RL2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0340000000C142", + "EventName": "PM_MRK_DATA_FROM_RL2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0300000010C142", + "EventName": "PM_MRK_INST_FROM_RL2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0340000020C142", + "EventName": "PM_MRK_DATA_FROM_RL2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a remote chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0D4100000000C142", + "EventName": "PM_MRK_INST_FROM_RMEM", + "BriefDescription": "The processor's instruction cache was reloaded from remote memory (MC slow) due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0D4040000000C142", + "EventName": "PM_MRK_DATA_FROM_RMEM", + "BriefDescription": "The processor's L1 data cache was reloaded from remote memory (MC slow) due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0D4100000010C142", + "EventName": "PM_MRK_INST_FROM_RMEM_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from remote memory (MC slow) due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0D4040000020C142", + "EventName": "PM_MRK_DATA_FROM_RMEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from remote memory (MC slow) due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0D8040000000C142", + "EventName": "PM_MRK_DATA_FROM_R_OC_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0D8040000020C142", + "EventName": "PM_MRK_DATA_FROM_R_OC_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0DC040000000C142", + "EventName": "PM_MRK_DATA_FROM_R_OC_MEM", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0DC040000020C142", + "EventName": "PM_MRK_DATA_FROM_R_OC_MEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0D8100000000C142", + "EventName": "PM_MRK_INST_FROM_R_OC_ANY", + "BriefDescription": "The processor's instruction cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0D8140000000C142", + "EventName": "PM_MRK_DATA_FROM_R_OC_ANY", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0D8100000010C142", + "EventName": "PM_MRK_INST_FROM_R_OC_ANY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0D8140000020C142", + "EventName": "PM_MRK_DATA_FROM_R_OC_ANY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a remote chip's OpenCAPI cache or memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E0040000000C142", + "EventName": "PM_MRK_DATA_FROM_DL2_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E0040000020C142", + "EventName": "PM_MRK_DATA_FROM_DL2_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E4040000000C142", + "EventName": "PM_MRK_DATA_FROM_DL2_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E4040000020C142", + "EventName": "PM_MRK_DATA_FROM_DL2_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E0100000000C142", + "EventName": "PM_MRK_INST_FROM_DL2", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E0140000000C142", + "EventName": "PM_MRK_DATA_FROM_DL2", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E0100000010C142", + "EventName": "PM_MRK_INST_FROM_DL2_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E0140000020C142", + "EventName": "PM_MRK_DATA_FROM_DL2_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E8040000000C142", + "EventName": "PM_MRK_DATA_FROM_DL3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E8040000020C142", + "EventName": "PM_MRK_DATA_FROM_DL3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0EC040000000C142", + "EventName": "PM_MRK_DATA_FROM_DL3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0EC040000020C142", + "EventName": "PM_MRK_DATA_FROM_DL3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E8100000000C142", + "EventName": "PM_MRK_INST_FROM_DL3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E8140000000C142", + "EventName": "PM_MRK_DATA_FROM_DL3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E8100000010C142", + "EventName": "PM_MRK_INST_FROM_DL3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E8140000020C142", + "EventName": "PM_MRK_DATA_FROM_DL3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E0240000000C142", + "EventName": "PM_MRK_DATA_FROM_DL2L3_SHR", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E0240000020C142", + "EventName": "PM_MRK_DATA_FROM_DL2L3_SHR_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a valid line that was not in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E4240000000C142", + "EventName": "PM_MRK_DATA_FROM_DL2L3_MOD", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E4240000020C142", + "EventName": "PM_MRK_DATA_FROM_DL2L3_MOD_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded with a line in the M (exclusive) state from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E0300000000C142", + "EventName": "PM_MRK_INST_FROM_DL2L3", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E0340000000C142", + "EventName": "PM_MRK_DATA_FROM_DL2L3", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0E0300000010C142", + "EventName": "PM_MRK_INST_FROM_DL2L3_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0E0340000020C142", + "EventName": "PM_MRK_DATA_FROM_DL2L3_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a distant chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0F4100000000C142", + "EventName": "PM_MRK_INST_FROM_DMEM", + "BriefDescription": "The processor's instruction cache was reloaded from distant memory (MC slow) due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0F4040000000C142", + "EventName": "PM_MRK_DATA_FROM_DMEM", + "BriefDescription": "The processor's L1 data cache was reloaded from distant memory (MC slow) due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0F4100000010C142", + "EventName": "PM_MRK_INST_FROM_DMEM_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from distant memory (MC slow) due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0F4040000020C142", + "EventName": "PM_MRK_DATA_FROM_DMEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from distant memory (MC slow) due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0F8040000000C142", + "EventName": "PM_MRK_DATA_FROM_D_OC_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0F8040000020C142", + "EventName": "PM_MRK_DATA_FROM_D_OC_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0FC040000000C142", + "EventName": "PM_MRK_DATA_FROM_D_OC_MEM", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0FC040000020C142", + "EventName": "PM_MRK_DATA_FROM_D_OC_MEM_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0F8100000000C142", + "EventName": "PM_MRK_INST_FROM_D_OC_ANY", + "BriefDescription": "The processor's instruction cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0F8140000000C142", + "EventName": "PM_MRK_DATA_FROM_D_OC_ANY", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0F8100000010C142", + "EventName": "PM_MRK_INST_FROM_D_OC_ANY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0F8140000020C142", + "EventName": "PM_MRK_DATA_FROM_D_OC_ANY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from a distant chip's OpenCAPI cache or memory due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080B00000000C142", + "EventName": "PM_MRK_INST_FROM_ONCHIP_CACHE", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080B40000000C142", + "EventName": "PM_MRK_DATA_FROM_ONCHIP_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x080B00000010C142", + "EventName": "PM_MRK_INST_FROM_ONCHIP_CACHE_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x080B40000020C142", + "EventName": "PM_MRK_DATA_FROM_ONCHIP_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from the same chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0B00000000C142", + "EventName": "PM_MRK_INST_FROM_OFFCHIP_CACHE", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0B40000000C142", + "EventName": "PM_MRK_DATA_FROM_OFFCHIP_CACHE", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x0C0B00000010C142", + "EventName": "PM_MRK_INST_FROM_OFFCHIP_CACHE_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x0C0B40000020C142", + "EventName": "PM_MRK_DATA_FROM_OFFCHIP_CACHE_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from another core's L2 or L3 from a different chip due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x095900000000C142", + "EventName": "PM_MRK_INST_FROM_ANY_MEMORY", + "BriefDescription": "The processor's instruction cache was reloaded from any chip's memory (MC slow) due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x095840000000C142", + "EventName": "PM_MRK_DATA_FROM_ANY_MEMORY", + "BriefDescription": "The processor's L1 data cache was reloaded from any chip's memory (MC slow) due to a demand miss for a marked instruction." + }, + { + "EventCode": "0x095900000010C142", + "EventName": "PM_MRK_INST_FROM_ANY_MEMORY_ALL", + "BriefDescription": "The processor's instruction cache was reloaded from any chip's memory (MC slow) due to a demand miss or prefetch reload for a marked instruction." + }, + { + "EventCode": "0x095840000020C142", + "EventName": "PM_MRK_DATA_FROM_ANY_MEMORY_ALL", + "BriefDescription": "The processor's L1 data cache was reloaded from any chip's memory (MC slow) due to a demand miss or prefetch reload for a marked instruction." + } +] diff --git a/tools/perf/pmu-events/arch/powerpc/power10/metrics.json b/tools/perf/pmu-events/arch/powerpc/power10/metrics.json index 4d66b75c6ad5..a36621858ea3 100644 --- a/tools/perf/pmu-events/arch/powerpc/power10/metrics.json +++ b/tools/perf/pmu-events/arch/powerpc/power10/metrics.json @@ -434,6 +434,13 @@ "MetricName": "L1_INST_MISS_RATE", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of completed instructions that were demand fetches that missed the L1 and L2 instruction cache", + "MetricExpr": "PM_INST_FROM_L2MISS * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "General", + "MetricName": "L2_INST_MISS_RATE", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of completed instructions that were demand fetches that reloaded from beyond the L3 icache", "MetricExpr": "PM_INST_FROM_L3MISS / PM_RUN_INST_CMPL * 100", @@ -466,6 +473,13 @@ "MetricGroup": "General", "MetricName": "LOADS_PER_INST" }, + { + "BriefDescription": "Percentage of demand loads that reloaded from the L2 per completed instruction", + "MetricExpr": "PM_DATA_FROM_L2 * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L2_RATE", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of demand loads that reloaded from beyond the L2 per completed instruction", "MetricExpr": "PM_DATA_FROM_L2MISS / PM_RUN_INST_CMPL * 100", @@ -473,6 +487,34 @@ "MetricName": "DL1_RELOAD_FROM_L2_MISS_RATE", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of demand loads that reloaded using modified data from another core's L2 or L3 on a remote chip, per completed instruction", + "MetricExpr": "PM_DATA_FROM_RL2L3_MOD * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RL2L3_MOD_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded using shared data from another core's L2 or L3 on a remote chip, per completed instruction", + "MetricExpr": "PM_DATA_FROM_RL2L3_SHR * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RL2L3_SHR_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded from the L3 per completed instruction", + "MetricExpr": "PM_DATA_FROM_L3 * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L3_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded with data brought into the L3 by prefetch per completed instruction", + "MetricExpr": "PM_DATA_FROM_L3_MEPF * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L3_MEPF_RATE", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of demand loads that reloaded from beyond the L3 per completed instruction", "MetricExpr": "PM_DATA_FROM_L3MISS / PM_RUN_INST_CMPL * 100", @@ -480,6 +522,66 @@ "MetricName": "DL1_RELOAD_FROM_L3_MISS_RATE", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of demand loads that reloaded using modified data from another core's L2 or L3 on a distant chip, per completed instruction", + "MetricExpr": "PM_DATA_FROM_DL2L3_MOD * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DL2L3_MOD_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded using shared data from another core's L2 or L3 on a distant chip, per completed instruction", + "MetricExpr": "PM_DATA_FROM_DL2L3_SHR * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DL2L3_SHR_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded from local memory per completed instruction", + "MetricExpr": "PM_DATA_FROM_LMEM * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_LMEM_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded from remote memory per completed instruction", + "MetricExpr": "PM_DATA_FROM_RMEM * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RMEM_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand loads that reloaded from distant memory per completed instruction", + "MetricExpr": "PM_DATA_FROM_DMEM * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DMEM_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of data reloads from local memory per data reloads from any memory", + "MetricExpr": "PM_DATA_FROM_LMEM * 100 / (PM_DATA_FROM_LMEM + PM_DATA_FROM_RMEM + PM_DATA_FROM_DMEM)", + "MetricGroup": "Memory", + "MetricName": "MEM_LOCALITY", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Number of data reloads from local memory per data reloads from remote memory", + "MetricExpr": "PM_DATA_FROM_LMEM / PM_DATA_FROM_RMEM", + "MetricGroup": "Memory", + "MetricName": "LD_LMEM_PER_LD_RMEM" + }, + { + "BriefDescription": "Number of data reloads from local memory per data reloads from distant memory", + "MetricExpr": "PM_DATA_FROM_LMEM / PM_DATA_FROM_DMEM", + "MetricGroup": "Memory", + "MetricName": "LD_LMEM_PER_LD_DMEM" + }, + { + "BriefDescription": "Number of data reloads from local memory per data reloads from distant and remote memory", + "MetricExpr": "PM_DATA_FROM_LMEM / (PM_DATA_FROM_DMEM + PM_DATA_FROM_RMEM)", + "MetricGroup": "Memory", + "MetricName": "LD_LMEM_PER_LD_MEM" + }, { "BriefDescription": "Percentage of ITLB misses per completed run instruction", "MetricExpr": "PM_ITLB_MISS / PM_RUN_INST_CMPL * 100", @@ -487,6 +589,12 @@ "MetricName": "ITLB_MISS_RATE", "ScaleUnit": "1%" }, + { + "BriefDescription": "Number of data reloads from remote memory per data reloads from distant memory", + "MetricExpr": "PM_DATA_FROM_RMEM / PM_DATA_FROM_DMEM", + "MetricGroup": "Memory", + "MetricName": "LD_RMEM_PER_LD_DMEM" + }, { "BriefDescription": "Percentage of DERAT misses with 4k page size per completed instruction", "MetricExpr": "PM_DERAT_MISS_4K / PM_RUN_INST_CMPL * 100", @@ -501,6 +609,76 @@ "MetricName": "DERAT_64K_MISS_RATE", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of ICache misses that were reloaded from the L2", + "MetricExpr": "PM_INST_FROM_L2 * 100 / PM_L1_ICACHE_MISS", + "MetricGroup": "Instruction_Stats", + "MetricName": "INST_FROM_L2", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache misses that were reloaded from the L3", + "MetricExpr": "PM_INST_FROM_L3 * 100 / PM_L1_ICACHE_MISS", + "MetricGroup": "Instruction_Stats", + "MetricName": "INST_FROM_L3", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache misses that were reloaded from local memory", + "MetricExpr": "PM_INST_FROM_LMEM * 100 / PM_L1_ICACHE_MISS", + "MetricGroup": "Instruction_Stats", + "MetricName": "INST_FROM_LMEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache misses that were reloaded from remote memory", + "MetricExpr": "PM_INST_FROM_RMEM * 100 / PM_L1_ICACHE_MISS", + "MetricGroup": "Instruction_Stats", + "MetricName": "INST_FROM_RMEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache misses that were reloaded from distant memory", + "MetricExpr": "PM_INST_FROM_DMEM * 100 / PM_L1_ICACHE_MISS", + "MetricGroup": "Instruction_Stats", + "MetricName": "INST_FROM_DMEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache reloads from the L2 per completed instruction", + "MetricExpr": "PM_INST_FROM_L2 * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_L2_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache reloads from the L3 per completed instruction", + "MetricExpr": "PM_INST_FROM_L3 * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_L3_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache reloads from local memory per completed instruction", + "MetricExpr": "PM_INST_FROM_LMEM * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_LMEM_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache reloads from remote memory per completed instruction", + "MetricExpr": "PM_INST_FROM_RMEM * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_RMEM_RATE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of ICache reloads from distant memory per completed instruction", + "MetricExpr": "PM_INST_FROM_DMEM * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_DMEM_RATE", + "ScaleUnit": "1%" + }, { "BriefDescription": "Average number of run cycles per completed instruction", "MetricExpr": "PM_RUN_CYC / PM_RUN_INST_CMPL", @@ -607,6 +785,13 @@ "MetricName": "DL1_MISS_RELOADS", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from the local L2", + "MetricExpr": "PM_DATA_FROM_L2 * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L2", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of demand load misses that reloaded from beyond the local L2", "MetricExpr": "PM_DATA_FROM_L2MISS / PM_LD_DEMAND_MISS_L1 * 100", @@ -614,6 +799,13 @@ "MetricName": "DL1_RELOAD_FROM_L2_MISS", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from the local L3", + "MetricExpr": "PM_DATA_FROM_L3 * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L3", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of demand load misses that reloaded from beyond the local L3", "MetricExpr": "PM_DATA_FROM_L3MISS / PM_LD_DEMAND_MISS_L1 * 100", @@ -621,6 +813,188 @@ "MetricName": "DL1_RELOAD_FROM_L3_MISS", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from the local L3 with modified data", + "MetricExpr": "PM_DATA_FROM_L3_MEPF * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L3_MEPF", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on the same regent with modified data", + "MetricExpr": "PM_DATA_FROM_L21_REGENT_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L21_REGENT_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on the same regent with shared data", + "MetricExpr": "PM_DATA_FROM_L21_REGENT_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L21_REGENT_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on the same chip in a different regent with modified data", + "MetricExpr": "PM_DATA_FROM_L21_NON_REGENT_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L21_NON_REGENT_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on the same chip in a different regent with shared data", + "MetricExpr": "PM_DATA_FROM_L21_NON_REGENT_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L21_NON_REGENT_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on the same regent with modified data", + "MetricExpr": "PM_DATA_FROM_L31_REGENT_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L31_REGENT_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on the same regent with shared data", + "MetricExpr": "PM_DATA_FROM_L31_REGENT_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L31_REGENT_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on the same chip in a different regent with modified data", + "MetricExpr": "PM_DATA_FROM_L31_NON_REGENT_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L31_NON_REGENT_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on the same chip in a different regent with shared data", + "MetricExpr": "PM_DATA_FROM_L31_NON_REGENT_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L31_NON_REGENT_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on a remote chip with modified data", + "MetricExpr": "PM_DATA_FROM_RL2_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RL2_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on a remote chip with shared data", + "MetricExpr": "PM_DATA_FROM_RL2_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RL2_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on a remote chip with modified data", + "MetricExpr": "PM_DATA_FROM_RL3_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RL3_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on a remote chip with shared data", + "MetricExpr": "PM_DATA_FROM_RL3_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RL3_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on a distant chip with modified data", + "MetricExpr": "PM_DATA_FROM_DL2_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DL2_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L2 on a distant chip with shared data", + "MetricExpr": "PM_DATA_FROM_DL2_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DL2_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on a distant chip with modified data", + "MetricExpr": "PM_DATA_FROM_DL3_MOD * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DL3_MOD", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from another core's L3 on a distant chip with shared data", + "MetricExpr": "PM_DATA_FROM_DL3_SHR * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DL3_SHR", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from the local chip's memory", + "MetricExpr": "PM_DATA_FROM_LMEM * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_LMEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from the local chip's OpenCAPI Cache", + "MetricExpr": "PM_DATA_FROM_L_OC_CACHE * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L_OC_CACHE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from the local chip's OpenCAPI memory", + "MetricExpr": "PM_DATA_FROM_L_OC_MEM * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_L_OC_MEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from a remote chip's memory", + "MetricExpr": "PM_DATA_FROM_RMEM * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_RMEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from a remote chip's OpenCAPI Cache", + "MetricExpr": "PM_DATA_FROM_R_OC_CACHE * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_R_OC_CACHE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from a remote chip's OpenCAPI memory", + "MetricExpr": "PM_DATA_FROM_R_OC_MEM * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_R_OC_MEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from a distant chip's memory", + "MetricExpr": "PM_DATA_FROM_DMEM * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_DMEM", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from a distant chip's OpenCAPI Cache", + "MetricExpr": "PM_DATA_FROM_D_OC_CACHE * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_D_OC_CACHE", + "ScaleUnit": "1%" + }, + { + "BriefDescription": "Percentage of demand load misses that reloaded from a distant chip's OpenCAPI memory", + "MetricExpr": "PM_DATA_FROM_D_OC_MEM * 100 / PM_LD_DEMAND_MISS_L1", + "MetricGroup": "dL1_Reloads", + "MetricName": "DL1_RELOAD_FROM_D_OC_MEM", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of cycles stalled due to the NTC instruction waiting for a load miss to resolve from a source beyond the local L2 and local L3", "MetricExpr": "DMISS_L3MISS_STALL_CPI / RUN_CPI * 100", @@ -686,6 +1060,13 @@ "MetricName": "DERAT_MISS_RELOAD", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of ICache misses that were reloaded from beyond the local L2", + "MetricExpr": "PM_INST_FROM_L2MISS * 100 / PM_L1_ICACHE_MISS", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_L2_MISS", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of icache misses that were reloaded from beyond the local L3", "MetricExpr": "PM_INST_FROM_L3MISS / PM_L1_ICACHE_MISS * 100", @@ -693,6 +1074,13 @@ "MetricName": "INST_FROM_L3_MISS", "ScaleUnit": "1%" }, + { + "BriefDescription": "Percentage of ICache reloads from beyond the L2 per completed instruction", + "MetricExpr": "PM_INST_FROM_L2MISS * 100 / PM_RUN_INST_CMPL", + "MetricGroup": "Instruction_Misses", + "MetricName": "INST_FROM_L2_MISS_RATE", + "ScaleUnit": "1%" + }, { "BriefDescription": "Percentage of icache reloads from the beyond the L3 per completed instruction", "MetricExpr": "PM_INST_FROM_L3MISS / PM_RUN_INST_CMPL * 100", diff --git a/tools/perf/pmu-events/arch/powerpc/power10/others.json b/tools/perf/pmu-events/arch/powerpc/power10/others.json index 0e21e7ba1959..fcf8a8ebe7bd 100644 --- a/tools/perf/pmu-events/arch/powerpc/power10/others.json +++ b/tools/perf/pmu-events/arch/powerpc/power10/others.json @@ -89,11 +89,6 @@ "EventName": "PM_LD_DEMAND_MISS_L1", "BriefDescription": "The L1 cache was reloaded with a line that fulfills a demand miss request. Counted at reload time, before finish." }, - { - "EventCode": "0x300FE", - "EventName": "PM_DATA_FROM_L3MISS", - "BriefDescription": "The processor's data cache was reloaded from a source other than the local core's L1, L2, or L3 due to a demand miss." - }, { "EventCode": "0x40012", "EventName": "PM_L1_ICACHE_RELOADED_ALL", @@ -113,10 +108,5 @@ "EventCode": "0x400F0", "EventName": "PM_LD_DEMAND_MISS_L1_FIN", "BriefDescription": "Load missed L1, counted at finish time." - }, - { - "EventCode": "0x400FE", - "EventName": "PM_DATA_FROM_MEMORY", - "BriefDescription": "The processor's data cache was reloaded from local, remote, or distant memory due to a demand miss." } ] diff --git a/tools/perf/pmu-events/arch/powerpc/power10/pmc.json b/tools/perf/pmu-events/arch/powerpc/power10/pmc.json index c606ae03cd27..0e0253d0e757 100644 --- a/tools/perf/pmu-events/arch/powerpc/power10/pmc.json +++ b/tools/perf/pmu-events/arch/powerpc/power10/pmc.json @@ -195,7 +195,7 @@ "BriefDescription": "Threshold counter exceeded a value of 128." }, { - "EventCode": "0x400FA", + "EventCode": "0x500FA", "EventName": "PM_RUN_INST_CMPL", "BriefDescription": "PowerPC instruction completed while the run latch is set." } diff --git a/tools/perf/pmu-events/arch/powerpc/power10/translation.json b/tools/perf/pmu-events/arch/powerpc/power10/translation.json index ea73900d248a..a96f76797da0 100644 --- a/tools/perf/pmu-events/arch/powerpc/power10/translation.json +++ b/tools/perf/pmu-events/arch/powerpc/power10/translation.json @@ -9,11 +9,6 @@ "EventName": "PM_ST_CMPL", "BriefDescription": "Stores completed from S2Q (2nd-level store queue). This event includes regular stores, stcx and cache inhibited stores. The following operations are excluded (pteupdate, snoop tlbie complete, store atomics, miso, load atomic payloads, tlbie, tlbsync, slbieg, isync, msgsnd, slbiag, cpabort, copy, tcheck, tend, stsync, dcbst, icbi, dcbf, hwsync, lwsync, ptesync, eieio, msgsync)." }, - { - "EventCode": "0x200FE", - "EventName": "PM_DATA_FROM_L2MISS", - "BriefDescription": "The processor's L1 data cache was reloaded from a source beyond the local core's L2 due to a demand miss." - }, { "EventCode": "0x300F0", "EventName": "PM_ST_MISS_L1", diff --git a/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json index c7e7528db315..4d423b149ad1 100644 --- a/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json +++ b/tools/perf/pmu-events/arch/test/test_soc/sys/uncore.json @@ -12,5 +12,13 @@ "EventName": "sys_ccn_pmu.read_cycles", "Unit": "sys_ccn_pmu", "Compat": "0x01" + }, + { + "BriefDescription": "Counts total cache misses in first lookup result (high priority)", + "EventidCode": "0x1", + "NodeType": "0x5", + "EventName": "sys_cmn_pmu.hnf_cache_miss", + "Unit": "sys_cmn_pmu", + "Compat": "(434|436|43c|43a).*" } ] diff --git a/tools/perf/pmu-events/arch/x86/alderlake/adl-metrics.json b/tools/perf/pmu-events/arch/x86/alderlake/adl-metrics.json index c6780d5c456b..3388b58b8f1a 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/adl-metrics.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/adl-metrics.json @@ -99,7 +99,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" @@ -395,13 +395,13 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Instructions per Branch (lower number means higher occurance rate)", + "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)", "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES", "MetricName": "tma_info_inst_mix_ipbranch", "Unit": "cpu_atom" }, { - "BriefDescription": "Instruction per (near) call (lower number means higher occurance rate)", + "BriefDescription": "Instruction per (near) call (lower number means higher occurrence rate)", "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.CALL", "MetricName": "tma_info_inst_mix_ipcall", "Unit": "cpu_atom" @@ -726,7 +726,7 @@ "Unit": "cpu_atom" }, { - "BriefDescription": "Counts the numer of issue slots that result in retirement slots.", + "BriefDescription": "Counts the number of issue slots that result in retirement slots.", "DefaultMetricgroupName": "TopdownL1", "MetricExpr": "TOPDOWN_RETIRING.ALL / tma_info_core_slots", "MetricGroup": "Default;TopdownL1;tma_L1_group", diff --git a/tools/perf/pmu-events/arch/x86/alderlake/frontend.json b/tools/perf/pmu-events/arch/x86/alderlake/frontend.json index 81349100fe32..542ba4a81996 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/frontend.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/frontend.json @@ -394,31 +394,61 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled", + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CORE]", "EventCode": "0x9c", - "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE", - "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "EventName": "IDQ_BUBBLES.CORE", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CORE]", "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_core" }, { - "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled", + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "CounterMask": "6", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "CounterMask": "1", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_FE_WAS_OK", + "Invert": "1", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CORE]", + "EventCode": "0x9c", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", "CounterMask": "6", "EventCode": "0x9c", "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE", - "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_core" }, { - "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled", + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", "CounterMask": "1", "EventCode": "0x9c", "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK", "Invert": "1", - "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_core" diff --git a/tools/perf/pmu-events/arch/x86/alderlake/memory.json b/tools/perf/pmu-events/arch/x86/alderlake/memory.json index 73d92d5c9f9d..23d36164433f 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/memory.json @@ -248,7 +248,7 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache.", + "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache. [L3_MISS_LOCAL is alias to L3_MISS]", "EventCode": "0xB7", "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL", "MSRIndex": "0x1a6,0x1a7", @@ -278,7 +278,7 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache.", + "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache. [L3_MISS_LOCAL is alias to L3_MISS]", "EventCode": "0xB7", "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL", "MSRIndex": "0x1a6,0x1a7", diff --git a/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json b/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json index cb5b8611064b..f9876bef16da 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/pipeline.json @@ -238,6 +238,15 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of near taken branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0xc0", + "Unit": "cpu_atom" + }, { "BriefDescription": "Taken branch instructions retired.", "EventCode": "0xc4", @@ -411,6 +420,15 @@ "UMask": "0x7e", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of mispredicted near taken branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.", "EventCode": "0xc5", @@ -842,7 +860,7 @@ "Unit": "cpu_core" }, { - "BriefDescription": "INT_MISC.UNKNOWN_BRANCH_CYCLES", + "BriefDescription": "Bubble cycles of BAClear (Unknown Branch).", "EventCode": "0xad", "EventName": "INT_MISC.UNKNOWN_BRANCH_CYCLES", "MSRIndex": "0x3F7", @@ -1145,7 +1163,7 @@ "BriefDescription": "TMA slots wasted due to incorrect speculation by branch mispredictions", "EventCode": "0xa4", "EventName": "TOPDOWN.BR_MISPREDICT_SLOTS", - "PublicDescription": "Number of TMA slots that were wasted due to incorrect speculation by (any type of) branch mispredictions. This event estimates number of specualtive operations that were issued but not retired as well as the out-of-order engine recovery past a branch misprediction.", + "PublicDescription": "Number of TMA slots that were wasted due to incorrect speculation by (any type of) branch mispredictions. This event estimates number of speculative operations that were issued but not retired as well as the out-of-order engine recovery past a branch misprediction.", "SampleAfterValue": "10000003", "UMask": "0x8", "Unit": "cpu_core" diff --git a/tools/perf/pmu-events/arch/x86/alderlake/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/alderlake/uncore-interconnect.json index 34fc052d00e4..8bf020a9dfa8 100644 --- a/tools/perf/pmu-events/arch/x86/alderlake/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/alderlake/uncore-interconnect.json @@ -25,6 +25,7 @@ }, { "BriefDescription": "This event is deprecated. Refer to new event UNC_ARB_REQ_TRK_REQUEST.DRD", + "Deprecated": "1", "EventCode": "0x81", "EventName": "UNC_ARB_DAT_REQUESTS.RD", "PerPkg": "1", @@ -33,6 +34,7 @@ }, { "BriefDescription": "This event is deprecated. Refer to new event UNC_ARB_DAT_OCCUPANCY.ALL", + "Deprecated": "1", "EventCode": "0x85", "EventName": "UNC_ARB_IFA_OCCUPANCY.ALL", "PerPkg": "1", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/adln-metrics.json b/tools/perf/pmu-events/arch/x86/alderlaken/adln-metrics.json index 06e67e34e1bf..c150c14ac6ed 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/adln-metrics.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/adln-metrics.json @@ -328,12 +328,12 @@ "MetricName": "tma_info_inst_mix_idiv_uop_ratio" }, { - "BriefDescription": "Instructions per Branch (lower number means higher occurance rate)", + "BriefDescription": "Instructions per Branch (lower number means higher occurrence rate)", "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.ALL_BRANCHES", "MetricName": "tma_info_inst_mix_ipbranch" }, { - "BriefDescription": "Instruction per (near) call (lower number means higher occurance rate)", + "BriefDescription": "Instruction per (near) call (lower number means higher occurrence rate)", "MetricExpr": "INST_RETIRED.ANY / BR_INST_RETIRED.CALL", "MetricName": "tma_info_inst_mix_ipcall" }, @@ -616,7 +616,7 @@ "ScaleUnit": "100%" }, { - "BriefDescription": "Counts the numer of issue slots that result in retirement slots.", + "BriefDescription": "Counts the number of issue slots that result in retirement slots.", "DefaultMetricgroupName": "TopdownL1", "MetricExpr": "TOPDOWN_RETIRING.ALL / tma_info_core_slots", "MetricGroup": "Default;TopdownL1;tma_L1_group", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/memory.json b/tools/perf/pmu-events/arch/x86/alderlaken/memory.json index 37259d38a222..863a3ba2b4b2 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/memory.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/memory.json @@ -59,7 +59,7 @@ "UMask": "0x1" }, { - "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache.", + "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache. [L3_MISS_LOCAL is alias to L3_MISS]", "EventCode": "0xB7", "EventName": "OCR.DEMAND_DATA_RD.L3_MISS_LOCAL", "MSRIndex": "0x1a6,0x1a7", @@ -77,7 +77,7 @@ "UMask": "0x1" }, { - "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache.", + "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache. [L3_MISS_LOCAL is alias to L3_MISS]", "EventCode": "0xB7", "EventName": "OCR.DEMAND_RFO.L3_MISS_LOCAL", "MSRIndex": "0x1a6,0x1a7", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json b/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json index fa53ff11a509..3153bab527a9 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/pipeline.json @@ -90,6 +90,14 @@ "SampleAfterValue": "200003", "UMask": "0xf7" }, + { + "BriefDescription": "Counts the number of near taken branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0xc0" + }, { "BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.INDIRECT", "Deprecated": "1", @@ -183,6 +191,14 @@ "SampleAfterValue": "200003", "UMask": "0x7e" }, + { + "BriefDescription": "Counts the number of mispredicted near taken branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0x80" + }, { "BriefDescription": "This event is deprecated. Refer to new event BR_MISP_RETIRED.INDIRECT", "Deprecated": "1", diff --git a/tools/perf/pmu-events/arch/x86/alderlaken/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/alderlaken/uncore-interconnect.json index 4af695a5e755..8bf020a9dfa8 100644 --- a/tools/perf/pmu-events/arch/x86/alderlaken/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/alderlaken/uncore-interconnect.json @@ -7,6 +7,56 @@ "UMask": "0x1", "Unit": "ARB" }, + { + "BriefDescription": "Each cycle counts number of any coherent request at memory controller that were issued by any core.", + "EventCode": "0x85", + "EventName": "UNC_ARB_DAT_OCCUPANCY.ALL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "ARB" + }, + { + "BriefDescription": "Each cycle counts number of coherent reads pending on data return from memory controller that were issued by any core.", + "EventCode": "0x85", + "EventName": "UNC_ARB_DAT_OCCUPANCY.RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "ARB" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event UNC_ARB_REQ_TRK_REQUEST.DRD", + "Deprecated": "1", + "EventCode": "0x81", + "EventName": "UNC_ARB_DAT_REQUESTS.RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "ARB" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event UNC_ARB_DAT_OCCUPANCY.ALL", + "Deprecated": "1", + "EventCode": "0x85", + "EventName": "UNC_ARB_IFA_OCCUPANCY.ALL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "ARB" + }, + { + "BriefDescription": "Each cycle count number of 'valid' coherent Data Read entries . Such entry is defined as valid when it is allocated till deallocation. Doesn't include prefetches [This event is alias to UNC_ARB_TRK_OCCUPANCY.RD]", + "EventCode": "0x80", + "EventName": "UNC_ARB_REQ_TRK_OCCUPANCY.DRD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "ARB" + }, + { + "BriefDescription": "Number of all coherent Data Read entries. Doesn't include prefetches [This event is alias to UNC_ARB_TRK_REQUESTS.RD]", + "EventCode": "0x81", + "EventName": "UNC_ARB_REQ_TRK_REQUEST.DRD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "ARB" + }, { "BriefDescription": "Each cycle counts number of all outgoing valid entries in ReqTrk. Such entry is defined as valid from its allocation in ReqTrk till deallocation. Accounts for Coherent and non-coherent traffic.", "EventCode": "0x80", @@ -15,6 +65,14 @@ "UMask": "0x1", "Unit": "ARB" }, + { + "BriefDescription": "Each cycle count number of 'valid' coherent Data Read entries . Such entry is defined as valid when it is allocated till deallocation. Doesn't include prefetches [This event is alias to UNC_ARB_REQ_TRK_OCCUPANCY.DRD]", + "EventCode": "0x80", + "EventName": "UNC_ARB_TRK_OCCUPANCY.RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "ARB" + }, { "BriefDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.", "EventCode": "0x81", @@ -22,5 +80,13 @@ "PerPkg": "1", "UMask": "0x1", "Unit": "ARB" + }, + { + "BriefDescription": "Number of all coherent Data Read entries. Doesn't include prefetches [This event is alias to UNC_ARB_REQ_TRK_REQUEST.DRD]", + "EventCode": "0x81", + "EventName": "UNC_ARB_TRK_REQUESTS.RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "ARB" } ] diff --git a/tools/perf/pmu-events/arch/x86/bonnell/frontend.json b/tools/perf/pmu-events/arch/x86/bonnell/frontend.json index 8d2f4edfb597..42284c02c11d 100644 --- a/tools/perf/pmu-events/arch/x86/bonnell/frontend.json +++ b/tools/perf/pmu-events/arch/x86/bonnell/frontend.json @@ -63,7 +63,7 @@ "UMask": "0x2" }, { - "BriefDescription": "Non-CISC nacro instructions decoded", + "BriefDescription": "Non-CISC macro instructions decoded", "EventCode": "0xAA", "EventName": "MACRO_INSTS.NON_CISC_DECODED", "SampleAfterValue": "2000000", diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json b/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json index 8fc62b8f667d..e1f55fcfa0d0 100644 --- a/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json +++ b/tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json @@ -48,6 +48,12 @@ "MetricName": "C7_Pkg_Residency", "ScaleUnit": "100%" }, + { + "BriefDescription": "Uncore frequency per die [GHZ]", + "MetricExpr": "tma_info_system_socket_clks / #num_dies / duration_time / 1e9", + "MetricGroup": "SoC", + "MetricName": "UNCORE_FREQ" + }, { "BriefDescription": "Percentage of cycles spent in System Management Interrupts.", "MetricExpr": "((msr@aperf@ - cycles) / msr@aperf@ if msr@smi@ > 0 else 0)", @@ -652,7 +658,7 @@ }, { "BriefDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]", - "MetricExpr": "64 * (arb@event\\=0x81\\,umask\\=0x1@ + arb@event\\=0x84\\,umask\\=0x1@) / 1e6 / duration_time / 1e3", + "MetricExpr": "64 * (UNC_M_CAS_COUNT.RD + UNC_M_CAS_COUNT.WR) / 1e9 / duration_time", "MetricGroup": "HPC;Mem;MemoryBW;SoC;tma_issueBW", "MetricName": "tma_info_system_dram_bw_use", "PublicDescription": "Average external Memory Bandwidth Use for reads and writes [GB / sec]. Related metrics: tma_fb_full, tma_mem_bandwidth, tma_sq_full" @@ -690,6 +696,12 @@ "MetricGroup": "SMT", "MetricName": "tma_info_system_smt_2t_utilization" }, + { + "BriefDescription": "Socket actual clocks when any core is active on that socket", + "MetricExpr": "cbox_0@event\\=0x0@", + "MetricGroup": "SoC", + "MetricName": "tma_info_system_socket_clks" + }, { "BriefDescription": "Average Frequency Utilization relative nominal frequency", "MetricExpr": "tma_info_thread_clks / CPU_CLK_UNHALTED.REF_TSC", diff --git a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-interconnect.json index 8a327e0f1441..910395977a6e 100644 --- a/tools/perf/pmu-events/arch/x86/broadwellde/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/broadwellde/uncore-interconnect.json @@ -253,7 +253,7 @@ "EventCode": "0x4", "EventName": "UNC_I_RxR_BL_DRS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -261,7 +261,7 @@ "EventCode": "0x1", "EventName": "UNC_I_RxR_BL_DRS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -269,7 +269,7 @@ "EventCode": "0x7", "EventName": "UNC_I_RxR_BL_DRS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -277,7 +277,7 @@ "EventCode": "0x5", "EventName": "UNC_I_RxR_BL_NCB_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -285,7 +285,7 @@ "EventCode": "0x2", "EventName": "UNC_I_RxR_BL_NCB_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -293,7 +293,7 @@ "EventCode": "0x8", "EventName": "UNC_I_RxR_BL_NCB_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -301,7 +301,7 @@ "EventCode": "0x6", "EventName": "UNC_I_RxR_BL_NCS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -309,7 +309,7 @@ "EventCode": "0x3", "EventName": "UNC_I_RxR_BL_NCS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -317,7 +317,7 @@ "EventCode": "0x9", "EventName": "UNC_I_RxR_BL_NCS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { diff --git a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json index e61a23f68899..b9fb216bee16 100644 --- a/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json @@ -271,7 +271,7 @@ "EventCode": "0x4", "EventName": "UNC_I_RxR_BL_DRS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -279,7 +279,7 @@ "EventCode": "0x1", "EventName": "UNC_I_RxR_BL_DRS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -287,7 +287,7 @@ "EventCode": "0x7", "EventName": "UNC_I_RxR_BL_DRS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -295,7 +295,7 @@ "EventCode": "0x5", "EventName": "UNC_I_RxR_BL_NCB_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -303,7 +303,7 @@ "EventCode": "0x2", "EventName": "UNC_I_RxR_BL_NCB_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -311,7 +311,7 @@ "EventCode": "0x8", "EventName": "UNC_I_RxR_BL_NCB_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -319,7 +319,7 @@ "EventCode": "0x6", "EventName": "UNC_I_RxR_BL_NCS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -327,7 +327,7 @@ "EventCode": "0x3", "EventName": "UNC_I_RxR_BL_NCS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -335,7 +335,7 @@ "EventCode": "0x9", "EventName": "UNC_I_RxR_BL_NCS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { diff --git a/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json b/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json index fbb111e40829..84c132af3dfa 100644 --- a/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json +++ b/tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json @@ -1837,7 +1837,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json new file mode 100644 index 000000000000..ab09bd9fb409 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/cache.json @@ -0,0 +1,888 @@ +[ + { + "BriefDescription": "L1D.HWPF_MISS", + "EventCode": "0x51", + "EventName": "L1D.HWPF_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Counts the number of cache lines replaced in L1 data cache.", + "EventCode": "0x51", + "EventName": "L1D.REPLACEMENT", + "PublicDescription": "Counts L1D data line replacements including opportunistic replacements, and replacements that require stall-for-replace or block-for-replace.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailability.", + "EventCode": "0x48", + "EventName": "L1D_PEND_MISS.FB_FULL", + "PublicDescription": "Counts number of cycles a demand request has waited due to L1D Fill Buffer (FB) unavailability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailability.", + "CounterMask": "1", + "EdgeDetect": "1", + "EventCode": "0x48", + "EventName": "L1D_PEND_MISS.FB_FULL_PERIODS", + "PublicDescription": "Counts number of phases a demand request has waited due to L1D Fill Buffer (FB) unavailability. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event L1D_PEND_MISS.L2_STALLS", + "Deprecated": "1", + "EventCode": "0x48", + "EventName": "L1D_PEND_MISS.L2_STALL", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Number of cycles a demand request has waited due to L1D due to lack of L2 resources.", + "EventCode": "0x48", + "EventName": "L1D_PEND_MISS.L2_STALLS", + "PublicDescription": "Counts number of cycles a demand request has waited due to L1D due to lack of L2 resources. Demand requests include cacheable/uncacheable demand load, store, lock or SW prefetch accesses.", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Number of L1D misses that are outstanding", + "EventCode": "0x48", + "EventName": "L1D_PEND_MISS.PENDING", + "PublicDescription": "Counts number of L1D misses that are outstanding in each cycle, that is each cycle the number of Fill Buffers (FB) outstanding required by Demand Reads. FB either is held by demand loads, or it is held by non-demand loads and gets hit at least once by demand. The valid outstanding interval is defined until the FB deallocation by one of the following ways: from FB allocation, if FB is allocated by demand from the demand Hit FB, if it is allocated by hardware or software prefetch. Note: In the L1D, a Demand Read contains cacheable or noncacheable demand loads, including ones causing cache-line splits and reads due to page walks resulted from any request type.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles with L1D load Misses outstanding.", + "CounterMask": "1", + "EventCode": "0x48", + "EventName": "L1D_PEND_MISS.PENDING_CYCLES", + "PublicDescription": "Counts duration of L1D miss outstanding in cycles.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "L2 cache lines filling L2", + "EventCode": "0x25", + "EventName": "L2_LINES_IN.ALL", + "PublicDescription": "Counts the number of L2 cache lines filling the L2. Counting does not cover rejects.", + "SampleAfterValue": "100003", + "UMask": "0x1f" + }, + { + "BriefDescription": "L2_LINES_OUT.NON_SILENT", + "EventCode": "0x26", + "EventName": "L2_LINES_OUT.NON_SILENT", + "SampleAfterValue": "200003", + "UMask": "0x2" + }, + { + "BriefDescription": "Non-modified cache lines that are silently dropped by L2 cache when triggered by an L2 cache fill.", + "EventCode": "0x26", + "EventName": "L2_LINES_OUT.SILENT", + "PublicDescription": "Counts the number of lines that are silently dropped by L2 cache when triggered by an L2 cache fill. These lines are typically in Shared or Exclusive state. A non-threaded event.", + "SampleAfterValue": "200003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cache lines that have been L2 hardware prefetched but not used by demand accesses", + "EventCode": "0x26", + "EventName": "L2_LINES_OUT.USELESS_HWPF", + "PublicDescription": "Counts the number of cache lines that have been prefetched by the L2 hardware prefetcher but not used by demand access when evicted from the L2 cache", + "SampleAfterValue": "200003", + "UMask": "0x4" + }, + { + "BriefDescription": "All accesses to L2 cache [This event is alias to L2_RQSTS.REFERENCES]", + "EventCode": "0x24", + "EventName": "L2_REQUEST.ALL", + "PublicDescription": "Counts all requests that were hit or true misses in L2 cache. True-miss excludes misses that were merged with ongoing L2 misses. [This event is alias to L2_RQSTS.REFERENCES]", + "SampleAfterValue": "200003", + "UMask": "0xff" + }, + { + "BriefDescription": "Read requests with true-miss in L2 cache. [This event is alias to L2_RQSTS.MISS]", + "EventCode": "0x24", + "EventName": "L2_REQUEST.MISS", + "PublicDescription": "Counts read requests of any type with true-miss in the L2 cache. True-miss excludes L2 misses that were merged with ongoing L2 misses. [This event is alias to L2_RQSTS.MISS]", + "SampleAfterValue": "200003", + "UMask": "0x3f" + }, + { + "BriefDescription": "L2 code requests", + "EventCode": "0x24", + "EventName": "L2_RQSTS.ALL_CODE_RD", + "PublicDescription": "Counts the total number of L2 code requests.", + "SampleAfterValue": "200003", + "UMask": "0xe4" + }, + { + "BriefDescription": "Demand Data Read access L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.ALL_DEMAND_DATA_RD", + "PublicDescription": "Counts Demand Data Read requests accessing the L2 cache. These requests may hit or miss L2 cache. True-miss exclude misses that were merged with ongoing L2 misses. An access is counted once.", + "SampleAfterValue": "200003", + "UMask": "0xe1" + }, + { + "BriefDescription": "Demand requests that miss L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.ALL_DEMAND_MISS", + "PublicDescription": "Counts demand requests that miss L2 cache.", + "SampleAfterValue": "200003", + "UMask": "0x27" + }, + { + "BriefDescription": "Demand requests to L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.ALL_DEMAND_REFERENCES", + "PublicDescription": "Counts demand requests to L2 cache.", + "SampleAfterValue": "200003", + "UMask": "0xe7" + }, + { + "BriefDescription": "L2_RQSTS.ALL_HWPF", + "EventCode": "0x24", + "EventName": "L2_RQSTS.ALL_HWPF", + "SampleAfterValue": "200003", + "UMask": "0xf0" + }, + { + "BriefDescription": "RFO requests to L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.ALL_RFO", + "PublicDescription": "Counts the total number of RFO (read for ownership) requests to L2 cache. L2 RFO requests include both L1D demand RFO misses as well as L1D RFO prefetches.", + "SampleAfterValue": "200003", + "UMask": "0xe2" + }, + { + "BriefDescription": "L2 cache hits when fetching instructions, code reads.", + "EventCode": "0x24", + "EventName": "L2_RQSTS.CODE_RD_HIT", + "PublicDescription": "Counts L2 cache hits when fetching instructions, code reads.", + "SampleAfterValue": "200003", + "UMask": "0xc4" + }, + { + "BriefDescription": "L2 cache misses when fetching instructions", + "EventCode": "0x24", + "EventName": "L2_RQSTS.CODE_RD_MISS", + "PublicDescription": "Counts L2 cache misses when fetching instructions.", + "SampleAfterValue": "200003", + "UMask": "0x24" + }, + { + "BriefDescription": "Demand Data Read requests that hit L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.DEMAND_DATA_RD_HIT", + "PublicDescription": "Counts the number of demand Data Read requests initiated by load instructions that hit L2 cache.", + "SampleAfterValue": "200003", + "UMask": "0xc1" + }, + { + "BriefDescription": "Demand Data Read miss L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.DEMAND_DATA_RD_MISS", + "PublicDescription": "Counts demand Data Read requests with true-miss in the L2 cache. True-miss excludes misses that were merged with ongoing L2 misses. An access is counted once.", + "SampleAfterValue": "200003", + "UMask": "0x21" + }, + { + "BriefDescription": "L2_RQSTS.HWPF_MISS", + "EventCode": "0x24", + "EventName": "L2_RQSTS.HWPF_MISS", + "SampleAfterValue": "200003", + "UMask": "0x30" + }, + { + "BriefDescription": "Read requests with true-miss in L2 cache. [This event is alias to L2_REQUEST.MISS]", + "EventCode": "0x24", + "EventName": "L2_RQSTS.MISS", + "PublicDescription": "Counts read requests of any type with true-miss in the L2 cache. True-miss excludes L2 misses that were merged with ongoing L2 misses. [This event is alias to L2_REQUEST.MISS]", + "SampleAfterValue": "200003", + "UMask": "0x3f" + }, + { + "BriefDescription": "All accesses to L2 cache [This event is alias to L2_REQUEST.ALL]", + "EventCode": "0x24", + "EventName": "L2_RQSTS.REFERENCES", + "PublicDescription": "Counts all requests that were hit or true misses in L2 cache. True-miss excludes misses that were merged with ongoing L2 misses. [This event is alias to L2_REQUEST.ALL]", + "SampleAfterValue": "200003", + "UMask": "0xff" + }, + { + "BriefDescription": "RFO requests that hit L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.RFO_HIT", + "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that hit L2 cache.", + "SampleAfterValue": "200003", + "UMask": "0xc2" + }, + { + "BriefDescription": "RFO requests that miss L2 cache", + "EventCode": "0x24", + "EventName": "L2_RQSTS.RFO_MISS", + "PublicDescription": "Counts the RFO (Read-for-Ownership) requests that miss L2 cache.", + "SampleAfterValue": "200003", + "UMask": "0x22" + }, + { + "BriefDescription": "SW prefetch requests that hit L2 cache.", + "EventCode": "0x24", + "EventName": "L2_RQSTS.SWPF_HIT", + "PublicDescription": "Counts Software prefetch requests that hit the L2 cache. Accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions when FB is not full.", + "SampleAfterValue": "200003", + "UMask": "0xc8" + }, + { + "BriefDescription": "SW prefetch requests that miss L2 cache.", + "EventCode": "0x24", + "EventName": "L2_RQSTS.SWPF_MISS", + "PublicDescription": "Counts Software prefetch requests that miss the L2 cache. Accounts for PREFETCHNTA and PREFETCHT0/1/2 instructions when FB is not full.", + "SampleAfterValue": "200003", + "UMask": "0x28" + }, + { + "BriefDescription": "Core-originated cacheable requests that missed L3 (Except hardware prefetches to the L3)", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.MISS", + "PublicDescription": "Counts core-originated cacheable requests that miss the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches to the L1 and L2. It does not include hardware prefetches to the L3, and may not count other types of requests to the L3.", + "SampleAfterValue": "100003", + "UMask": "0x41" + }, + { + "BriefDescription": "Core-originated cacheable requests that refer to L3 (Except hardware prefetches to the L3)", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.REFERENCE", + "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches to the L1 and L2. It does not include hardware prefetches to the L3, and may not count other types of requests to the L3.", + "SampleAfterValue": "100003", + "UMask": "0x4f" + }, + { + "BriefDescription": "Retired load instructions.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.ALL_LOADS", + "PEBS": "1", + "PublicDescription": "Counts all retired load instructions. This event accounts for SW prefetch instructions of PREFETCHNTA or PREFETCHT0/1/2 or PREFETCHW.", + "SampleAfterValue": "1000003", + "UMask": "0x81" + }, + { + "BriefDescription": "Retired store instructions.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.ALL_STORES", + "PEBS": "1", + "PublicDescription": "Counts all retired store instructions.", + "SampleAfterValue": "1000003", + "UMask": "0x82" + }, + { + "BriefDescription": "All retired memory instructions.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.ANY", + "PEBS": "1", + "PublicDescription": "Counts all retired memory instructions - loads and stores.", + "SampleAfterValue": "1000003", + "UMask": "0x83" + }, + { + "BriefDescription": "Retired load instructions with locked access.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.LOCK_LOADS", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with locked access.", + "SampleAfterValue": "100007", + "UMask": "0x21" + }, + { + "BriefDescription": "Retired load instructions that split across a cacheline boundary.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.SPLIT_LOADS", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions that split across a cacheline boundary.", + "SampleAfterValue": "100003", + "UMask": "0x41" + }, + { + "BriefDescription": "Retired store instructions that split across a cacheline boundary.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.SPLIT_STORES", + "PEBS": "1", + "PublicDescription": "Counts retired store instructions that split across a cacheline boundary.", + "SampleAfterValue": "100003", + "UMask": "0x42" + }, + { + "BriefDescription": "Retired load instructions that miss the STLB.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.STLB_MISS_LOADS", + "PEBS": "1", + "PublicDescription": "Number of retired load instructions that (start a) miss in the 2nd-level TLB (STLB).", + "SampleAfterValue": "100003", + "UMask": "0x11" + }, + { + "BriefDescription": "Retired store instructions that miss the STLB.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.STLB_MISS_STORES", + "PEBS": "1", + "PublicDescription": "Number of retired store instructions that (start a) miss in the 2nd-level TLB (STLB).", + "SampleAfterValue": "100003", + "UMask": "0x12" + }, + { + "BriefDescription": "Completed demand load uops that miss the L1 d-cache.", + "EventCode": "0x43", + "EventName": "MEM_LOAD_COMPLETED.L1_MISS_ANY", + "PublicDescription": "Number of completed demand load requests that missed the L1 data cache including shadow misses (FB hits, merge to an ongoing L1D miss)", + "SampleAfterValue": "1000003", + "UMask": "0xfd" + }, + { + "BriefDescription": "Retired load instructions whose data sources were HitM responses from shared L3", + "Data_LA": "1", + "EventCode": "0xd2", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_FWD", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions whose data sources were HitM responses from shared L3.", + "SampleAfterValue": "20011", + "UMask": "0x4" + }, + { + "BriefDescription": "Retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.", + "Data_LA": "1", + "EventCode": "0xd2", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_MISS", + "PEBS": "1", + "PublicDescription": "Counts the retired load instructions whose data sources were L3 hit and cross-core snoop missed in on-pkg core cache.", + "SampleAfterValue": "20011", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired load instructions whose data sources were hits in L3 without snoops required", + "Data_LA": "1", + "EventCode": "0xd2", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NONE", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions whose data sources were hits in L3 without snoops required.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Retired load instructions whose data sources were L3 and cross-core snoop hits in on-pkg core cache", + "Data_LA": "1", + "EventCode": "0xd2", + "EventName": "MEM_LOAD_L3_HIT_RETIRED.XSNP_NO_FWD", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions whose data sources were L3 and cross-core snoop hits in on-pkg core cache.", + "SampleAfterValue": "20011", + "UMask": "0x2" + }, + { + "BriefDescription": "Retired load instructions which data sources missed L3 but serviced from local dram", + "Data_LA": "1", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_L3_MISS_RETIRED.LOCAL_DRAM", + "PEBS": "1", + "PublicDescription": "Retired load instructions which data sources missed L3 but serviced from local DRAM.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM", + "Data_LA": "1", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_DRAM", + "PEBS": "1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Retired load instructions whose data sources was forwarded from a remote cache", + "Data_LA": "1", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_FWD", + "PEBS": "1", + "PublicDescription": "Retired load instructions whose data sources was forwarded from a remote cache.", + "SampleAfterValue": "100007", + "UMask": "0x8" + }, + { + "BriefDescription": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM", + "Data_LA": "1", + "EventCode": "0xd3", + "EventName": "MEM_LOAD_L3_MISS_RETIRED.REMOTE_HITM", + "PEBS": "1", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Retired instructions with at least 1 uncacheable load or lock.", + "Data_LA": "1", + "EventCode": "0xd4", + "EventName": "MEM_LOAD_MISC_RETIRED.UC", + "PEBS": "1", + "PublicDescription": "Retired instructions with at least one load to uncacheable memory-type, or at least one cache-line split locked access (Bus Lock).", + "SampleAfterValue": "100007", + "UMask": "0x4" + }, + { + "BriefDescription": "Number of completed demand load requests that missed the L1, but hit the FB(fill buffer), because a preceding miss to the same cacheline initiated the line to be brought into L1, but data is not yet ready in L1.", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.FB_HIT", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with at least one uop was load missed in L1 but hit FB (Fill Buffers) due to preceding miss to the same cache line with data not ready.", + "SampleAfterValue": "100007", + "UMask": "0x40" + }, + { + "BriefDescription": "Retired load instructions with L1 cache hits as data sources", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.L1_HIT", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L1 data cache. This event includes all SW prefetches and lock instructions regardless of the data source.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired load instructions missed L1 cache as data sources", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.L1_MISS", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L1 cache.", + "SampleAfterValue": "200003", + "UMask": "0x8" + }, + { + "BriefDescription": "Retired load instructions with L2 cache hits as data sources", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.L2_HIT", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with L2 cache hits as data sources.", + "SampleAfterValue": "200003", + "UMask": "0x2" + }, + { + "BriefDescription": "Retired load instructions missed L2 cache as data sources", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.L2_MISS", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions missed L2 cache as data sources.", + "SampleAfterValue": "100021", + "UMask": "0x10" + }, + { + "BriefDescription": "Retired load instructions with L3 cache hits as data sources", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.L3_HIT", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with at least one uop that hit in the L3 cache.", + "SampleAfterValue": "100021", + "UMask": "0x4" + }, + { + "BriefDescription": "Retired load instructions missed L3 cache as data sources", + "Data_LA": "1", + "EventCode": "0xd1", + "EventName": "MEM_LOAD_RETIRED.L3_MISS", + "PEBS": "1", + "PublicDescription": "Counts retired load instructions with at least one uop that missed in the L3 cache.", + "SampleAfterValue": "50021", + "UMask": "0x20" + }, + { + "BriefDescription": "MEM_STORE_RETIRED.L2_HIT", + "EventCode": "0x44", + "EventName": "MEM_STORE_RETIRED.L2_HIT", + "SampleAfterValue": "200003", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired memory uops for any access", + "EventCode": "0xe5", + "EventName": "MEM_UOP_RETIRED.ANY", + "PublicDescription": "Number of retired micro-operations (uops) for load or store memory accesses", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that hit in the L3 or were snooped from another core's caches on the same socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.L3_HIT", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F803C0004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that resulted in a snoop hit a modified line in another core's caches which forwarded the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.L3_HIT.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10003C0004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that hit a modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.SNC_CACHE.HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1008000004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that either hit a non-modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.SNC_CACHE.HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x808000004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that hit in the L3 or were snooped from another core's caches on the same socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_HIT", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F803C0001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that resulted in a snoop hit a modified line in another core's caches which forwarded the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10003C0001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that resulted in a snoop that hit in another core, which did not forward the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_NO_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x4003C0001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that resulted in a snoop hit in another core's caches which forwarded the unmodified data to the requesting core.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x8003C0001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by a cache on a remote socket where a snoop hit a modified line in another core's caches which forwarded the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.REMOTE_CACHE.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1030000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by a cache on a remote socket where a snoop hit in another core's caches which forwarded the unmodified data to the requesting core.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.REMOTE_CACHE.SNOOP_HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x830000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that hit a modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.SNC_CACHE.HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1008000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that either hit a non-modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.SNC_CACHE.HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x808000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that hit in the L3 or were snooped from another core's caches on the same socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.L3_HIT", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F803C0002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that resulted in a snoop hit a modified line in another core's caches which forwarded the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10003C0002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that hit a modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.SNC_CACHE.HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1008000002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that either hit a non-modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.SNC_CACHE.HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x808000002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts hardware prefetches to the L3 only that hit in the L3 or were snooped from another core's caches on the same socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L3.L3_HIT", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x80082380", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that hit in the L3 or were snooped from another core's caches on the same socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_HIT", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F003C4477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that resulted in a snoop hit a modified line in another core's caches which forwarded the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_HIT.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10003C4477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that resulted in a snoop that hit in another core, which did not forward the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_HIT.SNOOP_HIT_NO_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x4003C4477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that resulted in a snoop hit in another core's caches which forwarded the unmodified data to the requesting core.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_HIT.SNOOP_HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x8003C4477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by a cache on a remote socket where a snoop was sent and data was returned (Modified or Not Modified).", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.REMOTE_CACHE.SNOOP_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1830004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by a cache on a remote socket where a snoop hit a modified line in another core's caches which forwarded the data.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.REMOTE_CACHE.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1030004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by a cache on a remote socket where a snoop hit in another core's caches which forwarded the unmodified data to the requesting core.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.REMOTE_CACHE.SNOOP_HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x830004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that hit a modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.SNC_CACHE.HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1008004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that either hit a non-modified line in a distant L3 Cache or were snooped from a distant core's L1/L2 caches on this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.SNC_CACHE.HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x808004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO), hardware prefetch RFOs (which bring data to L2), and software prefetches for exclusive ownership (PREFETCHW) that hit to a (M)odified cacheline in the L3 or snoop filter.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.RFO_TO_CORE.L3_HIT_M", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x1F80040022", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts streaming stores that hit in the L3 or were snooped from another core's caches on the same socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.STREAMING_WR.L3_HIT", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x80080800", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "OFFCORE_REQUESTS.ALL_REQUESTS", + "EventCode": "0x21", + "EventName": "OFFCORE_REQUESTS.ALL_REQUESTS", + "SampleAfterValue": "100003", + "UMask": "0x80" + }, + { + "BriefDescription": "Demand and prefetch data reads", + "EventCode": "0x21", + "EventName": "OFFCORE_REQUESTS.DATA_RD", + "PublicDescription": "Counts the demand and prefetch data reads. All Core Data Reads include cacheable 'Demands' and L2 prefetchers (not L3 prefetchers). Counting also covers reads due to page walks resulted from any request type.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Demand Data Read requests sent to uncore", + "EventCode": "0x21", + "EventName": "OFFCORE_REQUESTS.DEMAND_DATA_RD", + "PublicDescription": "Counts the Demand Data Read requests sent to uncore. Use it in conjunction with OFFCORE_REQUESTS_OUTSTANDING to determine average latency in the uncore.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event OFFCORE_REQUESTS_OUTSTANDING.DATA_RD", + "Deprecated": "1", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.ALL_DATA_RD", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD", + "CounterMask": "1", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DATA_RD", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Cycles where at least 1 outstanding demand data read request is pending.", + "CounterMask": "1", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_DATA_RD", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO", + "CounterMask": "1", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.CYCLES_WITH_DEMAND_RFO", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "OFFCORE_REQUESTS_OUTSTANDING.DATA_RD", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DATA_RD", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "For every cycle, increments by the number of outstanding demand data read requests pending.", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.DEMAND_DATA_RD", + "PublicDescription": "For every cycle, increments by the number of outstanding demand data read requests pending. Requests are considered outstanding from the time they miss the core's L2 cache until the transaction completion message is sent to the requestor.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts bus locks, accounts for cache line split locks and UC locks.", + "EventCode": "0x2c", + "EventName": "SQ_MISC.BUS_LOCK", + "PublicDescription": "Counts the more expensive bus lock needed to enforce cache coherency for certain memory accesses that need to be done atomically. Can be created by issuing an atomic instruction (via the LOCK prefix) which causes a cache line split or accesses uncacheable memory.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Number of PREFETCHNTA instructions executed.", + "EventCode": "0x40", + "EventName": "SW_PREFETCH_ACCESS.NTA", + "PublicDescription": "Counts the number of PREFETCHNTA instructions executed.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of PREFETCHW instructions executed.", + "EventCode": "0x40", + "EventName": "SW_PREFETCH_ACCESS.PREFETCHW", + "PublicDescription": "Counts the number of PREFETCHW instructions executed.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Number of PREFETCHT0 instructions executed.", + "EventCode": "0x40", + "EventName": "SW_PREFETCH_ACCESS.T0", + "PublicDescription": "Counts the number of PREFETCHT0 instructions executed.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of PREFETCHT1 or PREFETCHT2 instructions executed.", + "EventCode": "0x40", + "EventName": "SW_PREFETCH_ACCESS.T1_T2", + "PublicDescription": "Counts the number of PREFETCHT1 or PREFETCHT2 instructions executed.", + "SampleAfterValue": "100003", + "UMask": "0x4" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/floating-point.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/floating-point.json new file mode 100644 index 000000000000..4a9d211e9d4f --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/floating-point.json @@ -0,0 +1,193 @@ +[ + { + "BriefDescription": "ARITH.FPDIV_ACTIVE", + "CounterMask": "1", + "EventCode": "0xb0", + "EventName": "ARITH.FPDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all microcode FP assists.", + "EventCode": "0xc1", + "EventName": "ASSISTS.FP", + "PublicDescription": "Counts all microcode Floating Point assists.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "ASSISTS.SSE_AVX_MIX", + "EventCode": "0xc1", + "EventName": "ASSISTS.SSE_AVX_MIX", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "FP_ARITH_DISPATCHED.PORT_0", + "EventCode": "0xb3", + "EventName": "FP_ARITH_DISPATCHED.PORT_0", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "FP_ARITH_DISPATCHED.PORT_1", + "EventCode": "0xb3", + "EventName": "FP_ARITH_DISPATCHED.PORT_1", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "FP_ARITH_DISPATCHED.PORT_5", + "EventCode": "0xb3", + "EventName": "FP_ARITH_DISPATCHED.PORT_5", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_DOUBLE", + "PublicDescription": "Number of SSE/AVX computational 128-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.128B_PACKED_SINGLE", + "PublicDescription": "Number of SSE/AVX computational 128-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_DOUBLE", + "PublicDescription": "Number of SSE/AVX computational 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 4 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.256B_PACKED_SINGLE", + "PublicDescription": "Number of SSE/AVX computational 256-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RCP DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Number of SSE/AVX computational 128-bit packed single and 256-bit packed double precision FP instructions retired; some instructions will count twice as noted below. Each count represents 2 or/and 4 computation operations, 1 for each element. Applies to SSE* and AVX* packed single precision and packed double precision FP instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.4_FLOPS", + "PublicDescription": "Number of SSE/AVX computational 128-bit packed single precision and 256-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 2 or/and 4 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point and packed double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX RCP14 RSQRT14 SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x18" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_DOUBLE", + "PublicDescription": "Number of SSE/AVX computational 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x40" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.512B_PACKED_SINGLE", + "PublicDescription": "Number of SSE/AVX computational 512-bit packed single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 16 computation operations, one for each element. Applies to SSE* and AVX* packed single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT14 RCP14 FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x80" + }, + { + "BriefDescription": "Number of SSE/AVX computational 256-bit packed single precision and 512-bit packed double precision FP instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, 1 for each element. Applies to SSE* and AVX* packed single precision and double precision FP instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RSQRT14 RCP RCP14 DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.8_FLOPS", + "PublicDescription": "Number of SSE/AVX computational 256-bit packed single precision and 512-bit packed double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 8 computation operations, one for each element. Applies to SSE* and AVX* packed single precision and double precision floating-point instructions: ADD SUB HADD HSUB SUBADD MUL DIV MIN MAX SQRT RSQRT RSQRT14 RCP RCP14 DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x60" + }, + { + "BriefDescription": "Number of SSE/AVX computational scalar floating-point instructions retired; some instructions will count twice as noted below. Applies to SSE* and AVX* scalar, double and single precision floating-point: ADD SUB MUL DIV MIN MAX RCP14 RSQRT14 RANGE SQRT DPP FM(N)ADD/SUB. DPP and FM(N)ADD/SUB instructions count twice as they perform multiple calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.SCALAR", + "PublicDescription": "Number of SSE/AVX computational scalar single precision and double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.SCALAR_DOUBLE", + "PublicDescription": "Number of SSE/AVX computational scalar double precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar double precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element.", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.SCALAR_SINGLE", + "PublicDescription": "Number of SSE/AVX computational scalar single precision floating-point instructions retired; some instructions will count twice as noted below. Each count represents 1 computational operation. Applies to SSE* and AVX* scalar single precision floating-point instructions: ADD SUB MUL DIV MIN MAX SQRT RSQRT RCP FM(N)ADD/SUB. FM(N)ADD/SUB instructions count twice as they perform 2 calculations per element. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of any Vector retired FP arithmetic instructions", + "EventCode": "0xc7", + "EventName": "FP_ARITH_INST_RETIRED.VECTOR", + "PublicDescription": "Number of any Vector retired FP arithmetic instructions. The DAZ and FTZ flags in the MXCSR register need to be set when using these events.", + "SampleAfterValue": "1000003", + "UMask": "0xfc" + }, + { + "BriefDescription": "FP_ARITH_INST_RETIRED2.128B_PACKED_HALF", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.128B_PACKED_HALF", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "FP_ARITH_INST_RETIRED2.256B_PACKED_HALF", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.256B_PACKED_HALF", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "FP_ARITH_INST_RETIRED2.512B_PACKED_HALF", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.512B_PACKED_HALF", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "FP_ARITH_INST_RETIRED2.COMPLEX_SCALAR_HALF", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.COMPLEX_SCALAR_HALF", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of all Scalar Half-Precision FP arithmetic instructions(1) retired - regular and complex.", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.SCALAR", + "PublicDescription": "FP_ARITH_INST_RETIRED2.SCALAR", + "SampleAfterValue": "100003", + "UMask": "0x3" + }, + { + "BriefDescription": "FP_ARITH_INST_RETIRED2.SCALAR_HALF", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.SCALAR_HALF", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of all Vector (also called packed) Half-Precision FP arithmetic instructions(1) retired.", + "EventCode": "0xcf", + "EventName": "FP_ARITH_INST_RETIRED2.VECTOR", + "PublicDescription": "FP_ARITH_INST_RETIRED2.VECTOR", + "SampleAfterValue": "100003", + "UMask": "0x1c" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/frontend.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/frontend.json new file mode 100644 index 000000000000..9e53da55d0c1 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/frontend.json @@ -0,0 +1,389 @@ +[ + { + "BriefDescription": "Clears due to Unknown Branches.", + "EventCode": "0x60", + "EventName": "BACLEARS.ANY", + "PublicDescription": "Number of times the front-end is resteered when it finds a branch instruction in a fetch line. This is called Unknown Branch which occurs for the first time a branch instruction is fetched or when the branch is not tracked by the BPU (Branch Prediction Unit) anymore.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Stalls caused by changing prefix length of the instruction.", + "EventCode": "0x87", + "EventName": "DECODE.LCP", + "PublicDescription": "Counts cycles that the Instruction Length decoder (ILD) stalls occurred due to dynamically changing prefix length of the decoded instruction (by operand size prefix instruction 0x66, address size prefix instruction 0x67 or REX.W for Intel64). Count is proportional to the number of prefixes in a 16B-line. This may result in a three-cycle penalty for each LCP (Length changing prefix) in a 16-byte chunk.", + "SampleAfterValue": "500009", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles the Microcode Sequencer is busy.", + "EventCode": "0x87", + "EventName": "DECODE.MS_BUSY", + "SampleAfterValue": "500009", + "UMask": "0x2" + }, + { + "BriefDescription": "DSB-to-MITE switch true penalty cycles.", + "EventCode": "0x61", + "EventName": "DSB2MITE_SWITCHES.PENALTY_CYCLES", + "PublicDescription": "Decode Stream Buffer (DSB) is a Uop-cache that holds translations of previously fetched instructions that were decoded by the legacy x86 decode pipeline (MITE). This event counts fetch penalty cycles when a transition occurs from DSB to MITE.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Retired Instructions who experienced DSB miss.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ANY_DSB_MISS", + "MSRIndex": "0x3F7", + "MSRValue": "0x1", + "PEBS": "1", + "PublicDescription": "Counts retired Instructions that experienced DSB (Decode stream buffer i.e. the decoded instruction-cache) miss.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired Instructions who experienced a critical DSB miss.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.DSB_MISS", + "MSRIndex": "0x3F7", + "MSRValue": "0x11", + "PEBS": "1", + "PublicDescription": "Number of retired Instructions that experienced a critical DSB (Decode stream buffer i.e. the decoded instruction-cache) miss. Critical means stalls were exposed to the back-end as a result of the DSB miss.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired Instructions who experienced iTLB true miss.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.ITLB_MISS", + "MSRIndex": "0x3F7", + "MSRValue": "0x14", + "PEBS": "1", + "PublicDescription": "Counts retired Instructions that experienced iTLB (Instruction TLB) true miss.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired Instructions who experienced Instruction L1 Cache true miss.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.L1I_MISS", + "MSRIndex": "0x3F7", + "MSRValue": "0x12", + "PEBS": "1", + "PublicDescription": "Counts retired Instructions who experienced Instruction L1 Cache true miss.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired Instructions who experienced Instruction L2 Cache true miss.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.L2_MISS", + "MSRIndex": "0x3F7", + "MSRValue": "0x13", + "PEBS": "1", + "PublicDescription": "Counts retired Instructions who experienced Instruction L2 Cache true miss.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions after front-end starvation of at least 1 cycle", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_1", + "MSRIndex": "0x3F7", + "MSRValue": "0x600106", + "PEBS": "1", + "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 1 cycle which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_128", + "MSRIndex": "0x3F7", + "MSRValue": "0x608006", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 128 cycles which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 16 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_16", + "MSRIndex": "0x3F7", + "MSRValue": "0x601006", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 16 cycles. During this period the front-end delivered no uops.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions after front-end starvation of at least 2 cycles", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_2", + "MSRIndex": "0x3F7", + "MSRValue": "0x600206", + "PEBS": "1", + "PublicDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of at least 2 cycles which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_256", + "MSRIndex": "0x3F7", + "MSRValue": "0x610006", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 256 cycles which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end had at least 1 bubble-slot for a period of 2 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_2_BUBBLES_GE_1", + "MSRIndex": "0x3F7", + "MSRValue": "0x100206", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after the front-end had at least 1 bubble-slot for a period of 2 cycles. A bubble-slot is an empty issue-pipeline slot while there was no RAT stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 32 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_32", + "MSRIndex": "0x3F7", + "MSRValue": "0x602006", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 32 cycles. During this period the front-end delivered no uops.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_4", + "MSRIndex": "0x3F7", + "MSRValue": "0x600406", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 4 cycles which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_512", + "MSRIndex": "0x3F7", + "MSRValue": "0x620006", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 512 cycles which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_64", + "MSRIndex": "0x3F7", + "MSRValue": "0x604006", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 64 cycles which was not interrupted by a back-end stall.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired instructions that are fetched after an interval where the front-end delivered no uops for a period of 8 cycles which was not interrupted by a back-end stall.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.LATENCY_GE_8", + "MSRIndex": "0x3F7", + "MSRValue": "0x600806", + "PEBS": "1", + "PublicDescription": "Counts retired instructions that are delivered to the back-end after a front-end stall of at least 8 cycles. During this period the front-end delivered no uops.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "FRONTEND_RETIRED.MS_FLOWS", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.MS_FLOWS", + "MSRIndex": "0x3F7", + "MSRValue": "0x8", + "PEBS": "1", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired Instructions who experienced STLB (2nd level TLB) true miss.", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.STLB_MISS", + "MSRIndex": "0x3F7", + "MSRValue": "0x15", + "PEBS": "1", + "PublicDescription": "Counts retired Instructions that experienced STLB (2nd level TLB) true miss.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "FRONTEND_RETIRED.UNKNOWN_BRANCH", + "EventCode": "0xc6", + "EventName": "FRONTEND_RETIRED.UNKNOWN_BRANCH", + "MSRIndex": "0x3F7", + "MSRValue": "0x17", + "PEBS": "1", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache miss.", + "EventCode": "0x80", + "EventName": "ICACHE_DATA.STALLS", + "PublicDescription": "Counts cycles where a code line fetch is stalled due to an L1 instruction cache miss. The decode pipeline works at a 32 Byte granularity.", + "SampleAfterValue": "500009", + "UMask": "0x4" + }, + { + "BriefDescription": "Cycles where a code fetch is stalled due to L1 instruction cache tag miss.", + "EventCode": "0x83", + "EventName": "ICACHE_TAG.STALLS", + "PublicDescription": "Counts cycles where a code fetch is stalled due to L1 instruction cache tag miss.", + "SampleAfterValue": "200003", + "UMask": "0x4" + }, + { + "BriefDescription": "Cycles Decode Stream Buffer (DSB) is delivering any Uop", + "CounterMask": "1", + "EventCode": "0x79", + "EventName": "IDQ.DSB_CYCLES_ANY", + "PublicDescription": "Counts the number of cycles uops were delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.", + "SampleAfterValue": "2000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Cycles DSB is delivering optimal number of Uops", + "CounterMask": "6", + "EventCode": "0x79", + "EventName": "IDQ.DSB_CYCLES_OK", + "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).", + "SampleAfterValue": "2000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path", + "EventCode": "0x79", + "EventName": "IDQ.DSB_UOPS", + "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the Decode Stream Buffer (DSB) path.", + "SampleAfterValue": "2000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Cycles MITE is delivering any Uop", + "CounterMask": "1", + "EventCode": "0x79", + "EventName": "IDQ.MITE_CYCLES_ANY", + "PublicDescription": "Counts the number of cycles uops were delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Cycles MITE is delivering optimal number of Uops", + "CounterMask": "6", + "EventCode": "0x79", + "EventName": "IDQ.MITE_CYCLES_OK", + "PublicDescription": "Counts the number of cycles where optimal number of uops was delivered to the Instruction Decode Queue (IDQ) from the MITE (legacy decode pipeline) path. During these cycles uops are not being delivered from the Decode Stream Buffer (DSB).", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) from MITE path", + "EventCode": "0x79", + "EventName": "IDQ.MITE_UOPS", + "PublicDescription": "Counts the number of uops delivered to Instruction Decode Queue (IDQ) from the MITE path. This also means that uops are not being delivered from the Decode Stream Buffer (DSB).", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Cycles when uops are being delivered to IDQ while MS is busy", + "CounterMask": "1", + "EventCode": "0x79", + "EventName": "IDQ.MS_CYCLES_ANY", + "PublicDescription": "Counts cycles during which uops are being delivered to Instruction Decode Queue (IDQ) while the Microcode Sequencer (MS) is busy. Uops maybe initiated by Decode Stream Buffer (DSB) or MITE.", + "SampleAfterValue": "2000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Number of switches from DSB or MITE to the MS", + "CounterMask": "1", + "EdgeDetect": "1", + "EventCode": "0x79", + "EventName": "IDQ.MS_SWITCHES", + "PublicDescription": "Number of switches from DSB (Decode Stream Buffer) or MITE (legacy decode pipeline) to the Microcode Sequencer.", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Uops delivered to IDQ while MS is busy", + "EventCode": "0x79", + "EventName": "IDQ.MS_UOPS", + "PublicDescription": "Counts the total number of uops delivered by the Microcode Sequencer (MS).", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CORE]", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CORE", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "CounterMask": "6", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "CounterMask": "1", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_FE_WAS_OK", + "Invert": "1", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CORE]", + "EventCode": "0x9c", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", + "CounterMask": "6", + "EventCode": "0x9c", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", + "CounterMask": "1", + "EventCode": "0x9c", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK", + "Invert": "1", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/memory.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/memory.json new file mode 100644 index 000000000000..e8bf7c9c44e1 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/memory.json @@ -0,0 +1,343 @@ +[ + { + "BriefDescription": "Execution stalls while L3 cache miss demand load is outstanding.", + "CounterMask": "6", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.STALLS_L3_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x6" + }, + { + "BriefDescription": "Number of machine clears due to memory ordering conflicts.", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING", + "PublicDescription": "Counts the number of Machine Clears detected dye to memory ordering. Memory Ordering Machine Clears may apply when a memory read may not conform to the memory ordering rules of the x86 architecture", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.", + "CounterMask": "2", + "EventCode": "0x47", + "EventName": "MEMORY_ACTIVITY.CYCLES_L1D_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.", + "CounterMask": "3", + "EventCode": "0x47", + "EventName": "MEMORY_ACTIVITY.STALLS_L1D_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Execution stalls while L2 cache miss demand cacheable load request is outstanding.", + "CounterMask": "5", + "EventCode": "0x47", + "EventName": "MEMORY_ACTIVITY.STALLS_L2_MISS", + "PublicDescription": "Execution stalls while L2 cache miss demand cacheable load request is outstanding (will not count for uncacheable demand requests e.g. bus lock).", + "SampleAfterValue": "1000003", + "UMask": "0x5" + }, + { + "BriefDescription": "Execution stalls while L3 cache miss demand cacheable load request is outstanding.", + "CounterMask": "9", + "EventCode": "0x47", + "EventName": "MEMORY_ACTIVITY.STALLS_L3_MISS", + "PublicDescription": "Execution stalls while L3 cache miss demand cacheable load request is outstanding (will not count for uncacheable demand requests e.g. bus lock).", + "SampleAfterValue": "1000003", + "UMask": "0x9" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128", + "MSRIndex": "0x3F6", + "MSRValue": "0x80", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "1009", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16", + "MSRIndex": "0x3F6", + "MSRValue": "0x10", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "20011", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256", + "MSRIndex": "0x3F6", + "MSRValue": "0x100", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "503", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32", + "MSRIndex": "0x3F6", + "MSRValue": "0x20", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4", + "MSRIndex": "0x3F6", + "MSRValue": "0x4", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512", + "MSRIndex": "0x3F6", + "MSRValue": "0x200", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "101", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64", + "MSRIndex": "0x3F6", + "MSRValue": "0x40", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "2003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8", + "MSRIndex": "0x3F6", + "MSRValue": "0x8", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "50021", + "UMask": "0x1" + }, + { + "BriefDescription": "Retired memory store access operations. A PDist event for PEBS Store Latency Facility.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.STORE_SAMPLE", + "PEBS": "2", + "PublicDescription": "Counts Retired memory accesses with at least 1 store operation. This PEBS event is the precisely-distributed (PDist) trigger covering all stores uops for sampling by the PEBS Store Latency Facility. The facility is described in Intel SDM Volume 3 section 19.9.8", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that were not supplied by the local socket's L1, L2, or L3 caches.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were not supplied by the local socket's L1, L2, or L3 caches.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the local socket's L1, L2, or L3 caches.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F3FC00002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts hardware prefetches to the L3 only that missed the local socket's L1, L2, and L3 caches.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L3.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x94002380", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts hardware prefetches to the L3 only that were not supplied by the local socket's L1, L2, or L3 caches and the cacheline is homed locally.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L3.L3_MISS_LOCAL", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x84002380", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were not supplied by the local socket's L1, L2, or L3 caches.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F3FC04477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were not supplied by the local socket's L1, L2, or L3 caches and the cacheline is homed locally.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_MISS_LOCAL", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F04C04477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that missed the L3 Cache and were supplied by the local socket (DRAM or PMM), whether or not in Sub NUMA Cluster(SNC) Mode. In SNC Mode counts PMM or DRAM accesses that are controlled by the close or distant SNC Cluster. It does not count misses to the L3 which go to Local CXL Type 2 Memory or Local Non DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.L3_MISS_LOCAL_SOCKET", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x70CC04477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts streaming stores that missed the local socket's L1, L2, and L3 caches.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.STREAMING_WR.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x94000800", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts streaming stores that were not supplied by the local socket's L1, L2, or L3 caches and the cacheline is homed locally.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.STREAMING_WR.L3_MISS_LOCAL", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x84000800", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data read requests that miss the L3 cache.", + "EventCode": "0x21", + "EventName": "OFFCORE_REQUESTS.L3_MISS_DEMAND_DATA_RD", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "For every cycle, increments by the number of demand data read requests pending that are known to have missed the L3 cache.", + "EventCode": "0x20", + "EventName": "OFFCORE_REQUESTS_OUTSTANDING.L3_MISS_DEMAND_DATA_RD", + "PublicDescription": "For every cycle, increments by the number of demand data read requests pending that are known to have missed the L3 cache. Note that this does not capture all elapsed cycles while requests are outstanding - only cycles from when the requests were known by the requesting core to have missed the L3 cache.", + "SampleAfterValue": "2000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Number of times an RTM execution aborted.", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.ABORTED", + "PublicDescription": "Counts the number of times RTM abort was triggered.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "Number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt)", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.ABORTED_EVENTS", + "PublicDescription": "Counts the number of times an RTM execution aborted due to none of the previous 4 categories (e.g. interrupt).", + "SampleAfterValue": "100003", + "UMask": "0x80" + }, + { + "BriefDescription": "Number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts)", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.ABORTED_MEM", + "PublicDescription": "Counts the number of times an RTM execution aborted due to various memory events (e.g. read/write capacity and conflicts).", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Number of times an RTM execution aborted due to incompatible memory type", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.ABORTED_MEMTYPE", + "PublicDescription": "Counts the number of times an RTM execution aborted due to incompatible memory type.", + "SampleAfterValue": "100003", + "UMask": "0x40" + }, + { + "BriefDescription": "Number of times an RTM execution aborted due to HLE-unfriendly instructions", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.ABORTED_UNFRIENDLY", + "PublicDescription": "Counts the number of times an RTM execution aborted due to HLE-unfriendly instructions.", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Number of times an RTM execution successfully committed", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.COMMIT", + "PublicDescription": "Counts the number of times RTM commit succeeded.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of times an RTM execution started.", + "EventCode": "0xc9", + "EventName": "RTM_RETIRED.START", + "PublicDescription": "Counts the number of times we entered an RTM region. Does not count nested transactions.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Speculatively counts the number of TSX aborts due to a data capacity limitation for transactional reads", + "EventCode": "0x54", + "EventName": "TX_MEM.ABORT_CAPACITY_READ", + "PublicDescription": "Speculatively counts the number of Transactional Synchronization Extensions (TSX) aborts due to a data capacity limitation for transactional reads", + "SampleAfterValue": "100003", + "UMask": "0x80" + }, + { + "BriefDescription": "Speculatively counts the number of TSX aborts due to a data capacity limitation for transactional writes.", + "EventCode": "0x54", + "EventName": "TX_MEM.ABORT_CAPACITY_WRITE", + "PublicDescription": "Speculatively counts the number of Transactional Synchronization Extensions (TSX) aborts due to a data capacity limitation for transactional writes.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of times a transactional abort was signaled due to a data conflict on a transactionally accessed address", + "EventCode": "0x54", + "EventName": "TX_MEM.ABORT_CONFLICT", + "PublicDescription": "Counts the number of times a TSX line had a cache conflict.", + "SampleAfterValue": "100003", + "UMask": "0x1" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/other.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/other.json new file mode 100644 index 000000000000..2f375a6badcd --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/other.json @@ -0,0 +1,315 @@ +[ + { + "BriefDescription": "ASSISTS.PAGE_FAULT", + "EventCode": "0xc1", + "EventName": "ASSISTS.PAGE_FAULT", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts the cycles where the AMX (Advance Matrix Extension) unit is busy performing an operation.", + "EventCode": "0xb7", + "EventName": "EXE.AMX_BUSY", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that were supplied by DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x73C000004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that were supplied by DRAM attached to this socket, unless in Sub NUMA Cluster(SNC) Mode. In SNC Mode counts only those DRAM accesses that are controlled by the close SNC Cluster.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.LOCAL_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x104000004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand instruction fetches and L1 instruction cache prefetches that were supplied by DRAM on a distant memory controller of this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_CODE_RD.SNC_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x708000004", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x73C000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by DRAM attached to this socket, unless in Sub NUMA Cluster(SNC) Mode. In SNC Mode counts only those DRAM accesses that are controlled by the close SNC Cluster.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.LOCAL_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x104000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by DRAM attached to another socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.REMOTE_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x730000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by DRAM on a distant memory controller of this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.SNC_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x708000001", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F3FFC0002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that were supplied by DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x73C000002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that were supplied by DRAM attached to this socket, unless in Sub NUMA Cluster(SNC) Mode. In SNC Mode counts only those DRAM accesses that are controlled by the close SNC Cluster.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.LOCAL_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x104000002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that were supplied by DRAM on a distant memory controller of this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.SNC_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x708000002", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts data load hardware prefetch requests to the L1 data cache that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L1D.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10400", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts hardware prefetches (which bring data to L2) that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L2.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10070", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts hardware prefetches to the L3 only that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L3.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x12380", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts hardware prefetches to the L3 only that were not supplied by the local socket's L1, L2, or L3 caches and the cacheline was homed in a remote socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.HWPF_L3.REMOTE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x90002380", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts writebacks of modified cachelines and streaming stores that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.MODIFIED_WRITE.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10808", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F3FFC4477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x73C004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by DRAM attached to this socket, unless in Sub NUMA Cluster(SNC) Mode. In SNC Mode counts only those DRAM accesses that are controlled by the close SNC Cluster.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.LOCAL_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x104004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by DRAM attached to this socket, whether or not in Sub NUMA Cluster(SNC) Mode. In SNC Mode counts DRAM accesses that are controlled by the close or distant SNC Cluster.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.LOCAL_SOCKET_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x70C004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were not supplied by the local socket's L1, L2, or L3 caches and were supplied by a remote socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.REMOTE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3F33004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by DRAM attached to another socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.REMOTE_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x730004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by DRAM or PMM attached to another socket.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.REMOTE_MEMORY", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x733004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts all (cacheable) data read, code read and RFO requests including demands and prefetches to the core caches (L1 or L2) that were supplied by DRAM on a distant memory controller of this socket when the system is in SNC (sub-NUMA cluster) mode.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.READS_TO_CORE.SNC_DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x708004477", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts streaming stores that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.STREAMING_WR.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10800", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts Demand RFOs, ItoM's, PREFECTHW's, Hardware RFO Prefetches to the L1/L2 and Streaming stores that likely resulted in a store to Memory (DRAM or PMM)", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.WRITE_ESTIMATE.MEMORY", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0xFBFF80822", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when Reservation Station (RS) is empty for the thread.", + "EventCode": "0xa5", + "EventName": "RS.EMPTY", + "PublicDescription": "Counts cycles during which the reservation station (RS) is empty for this logical processor. This is usually caused when the front-end pipeline runs into starvation periods (e.g. branch mispredictions or i-cache misses)", + "SampleAfterValue": "1000003", + "UMask": "0x7" + }, + { + "BriefDescription": "Counts end of periods where the Reservation Station (RS) was empty.", + "CounterMask": "1", + "EdgeDetect": "1", + "EventCode": "0xa5", + "EventName": "RS.EMPTY_COUNT", + "Invert": "1", + "PublicDescription": "Counts end of periods where the Reservation Station (RS) was empty. Could be useful to closely sample on front-end latency issues (see the FRONTEND_RETIRED event of designated precise events)", + "SampleAfterValue": "100003", + "UMask": "0x7" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event RS.EMPTY_COUNT", + "CounterMask": "1", + "Deprecated": "1", + "EdgeDetect": "1", + "EventCode": "0xa5", + "EventName": "RS_EMPTY.COUNT", + "Invert": "1", + "SampleAfterValue": "100003", + "UMask": "0x7" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event RS.EMPTY", + "Deprecated": "1", + "EventCode": "0xa5", + "EventName": "RS_EMPTY.CYCLES", + "SampleAfterValue": "1000003", + "UMask": "0x7" + }, + { + "BriefDescription": "Cycles the uncore cannot take further requests", + "CounterMask": "1", + "EventCode": "0x2d", + "EventName": "XQ.FULL_CYCLES", + "PublicDescription": "number of cycles when the thread is active and the uncore cannot take any further requests (for example prefetches, loads or stores initiated by the Core that miss the L2 cache).", + "SampleAfterValue": "1000003", + "UMask": "0x1" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/pipeline.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/pipeline.json new file mode 100644 index 000000000000..6dcf3b763af4 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/pipeline.json @@ -0,0 +1,975 @@ +[ + { + "BriefDescription": "AMX retired arithmetic BF16 operations.", + "EventCode": "0xce", + "EventName": "AMX_OPS_RETIRED.BF16", + "PublicDescription": "Number of AMX-based retired arithmetic bfloat16 (BF16) floating-point operations. Counts TDPBF16PS FP instructions. SW to use operation multiplier of 4", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "AMX retired arithmetic integer 8-bit operations.", + "EventCode": "0xce", + "EventName": "AMX_OPS_RETIRED.INT8", + "PublicDescription": "Number of AMX-based retired arithmetic integer operations of 8-bit width source operands. Counts TDPB[SS,UU,US,SU]D instructions. SW should use operation multiplier of 8.", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event ARITH.DIV_ACTIVE", + "CounterMask": "1", + "Deprecated": "1", + "EventCode": "0xb0", + "EventName": "ARITH.DIVIDER_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x9" + }, + { + "BriefDescription": "Cycles when divide unit is busy executing divide or square root operations.", + "CounterMask": "1", + "EventCode": "0xb0", + "EventName": "ARITH.DIV_ACTIVE", + "PublicDescription": "Counts cycles when divide unit is busy executing divide or square root operations. Accounts for integer and floating-point operations.", + "SampleAfterValue": "1000003", + "UMask": "0x9" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event ARITH.FPDIV_ACTIVE", + "CounterMask": "1", + "Deprecated": "1", + "EventCode": "0xb0", + "EventName": "ARITH.FP_DIVIDER_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "This event counts the cycles the integer divider is busy.", + "CounterMask": "1", + "EventCode": "0xb0", + "EventName": "ARITH.IDIV_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event ARITH.IDIV_ACTIVE", + "CounterMask": "1", + "Deprecated": "1", + "EventCode": "0xb0", + "EventName": "ARITH.INT_DIVIDER_ACTIVE", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Number of occurrences where a microcode assist is invoked by hardware.", + "EventCode": "0xc1", + "EventName": "ASSISTS.ANY", + "PublicDescription": "Counts the number of occurrences where a microcode assist is invoked by hardware. Examples include AD (page Access Dirty), FP and AVX related assists.", + "SampleAfterValue": "100003", + "UMask": "0x1b" + }, + { + "BriefDescription": "All branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.ALL_BRANCHES", + "PEBS": "1", + "PublicDescription": "Counts all branch instructions retired.", + "SampleAfterValue": "400009" + }, + { + "BriefDescription": "Conditional branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND", + "PEBS": "1", + "PublicDescription": "Counts conditional branch instructions retired.", + "SampleAfterValue": "400009", + "UMask": "0x11" + }, + { + "BriefDescription": "Not taken branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_NTAKEN", + "PEBS": "1", + "PublicDescription": "Counts not taken branch instructions retired.", + "SampleAfterValue": "400009", + "UMask": "0x10" + }, + { + "BriefDescription": "Taken conditional branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.COND_TAKEN", + "PEBS": "1", + "PublicDescription": "Counts taken conditional branch instructions retired.", + "SampleAfterValue": "400009", + "UMask": "0x1" + }, + { + "BriefDescription": "Far branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.FAR_BRANCH", + "PEBS": "1", + "PublicDescription": "Counts far branch instructions retired.", + "SampleAfterValue": "100007", + "UMask": "0x40" + }, + { + "BriefDescription": "Indirect near branch instructions retired (excluding returns)", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.INDIRECT", + "PEBS": "1", + "PublicDescription": "Counts near indirect branch instructions retired excluding returns. TSX abort is an indirect branch.", + "SampleAfterValue": "100003", + "UMask": "0x80" + }, + { + "BriefDescription": "Direct and indirect near call instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_CALL", + "PEBS": "1", + "PublicDescription": "Counts both direct and indirect near call instructions retired.", + "SampleAfterValue": "100007", + "UMask": "0x2" + }, + { + "BriefDescription": "Return instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_RETURN", + "PEBS": "1", + "PublicDescription": "Counts return instructions retired.", + "SampleAfterValue": "100007", + "UMask": "0x8" + }, + { + "BriefDescription": "Taken branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "PublicDescription": "Counts taken branch instructions retired.", + "SampleAfterValue": "400009", + "UMask": "0x20" + }, + { + "BriefDescription": "All mispredicted branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.ALL_BRANCHES", + "PEBS": "1", + "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.", + "SampleAfterValue": "400009" + }, + { + "BriefDescription": "Mispredicted conditional branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND", + "PEBS": "1", + "PublicDescription": "Counts mispredicted conditional branch instructions retired.", + "SampleAfterValue": "400009", + "UMask": "0x11" + }, + { + "BriefDescription": "Mispredicted non-taken conditional branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND_NTAKEN", + "PEBS": "1", + "PublicDescription": "Counts the number of conditional branch instructions retired that were mispredicted and the branch direction was not taken.", + "SampleAfterValue": "400009", + "UMask": "0x10" + }, + { + "BriefDescription": "number of branch instructions retired that were mispredicted and taken.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND_TAKEN", + "PEBS": "1", + "PublicDescription": "Counts taken conditional mispredicted branch instructions retired.", + "SampleAfterValue": "400009", + "UMask": "0x1" + }, + { + "BriefDescription": "Miss-predicted near indirect branch instructions retired (excluding returns)", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.INDIRECT", + "PEBS": "1", + "PublicDescription": "Counts miss-predicted near indirect branch instructions retired excluding returns. TSX abort is an indirect branch.", + "SampleAfterValue": "100003", + "UMask": "0x80" + }, + { + "BriefDescription": "Mispredicted indirect CALL retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.INDIRECT_CALL", + "PEBS": "1", + "PublicDescription": "Counts retired mispredicted indirect (near taken) CALL instructions, including both register and memory indirect.", + "SampleAfterValue": "400009", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "PublicDescription": "Counts number of near branch instructions retired that were mispredicted and taken.", + "SampleAfterValue": "400009", + "UMask": "0x20" + }, + { + "BriefDescription": "This event counts the number of mispredicted ret instructions retired. Non PEBS", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.RET", + "PEBS": "1", + "PublicDescription": "This is a non-precise version (that is, does not use PEBS) of the event that counts mispredicted return instructions retired.", + "SampleAfterValue": "100007", + "UMask": "0x8" + }, + { + "BriefDescription": "Core clocks when the thread is in the C0.1 light-weight slower wakeup time but more power saving optimized state.", + "EventCode": "0xec", + "EventName": "CPU_CLK_UNHALTED.C01", + "PublicDescription": "Counts core clocks when the thread is in the C0.1 light-weight slower wakeup time but more power saving optimized state. This state can be entered via the TPAUSE or UMWAIT instructions.", + "SampleAfterValue": "2000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Core clocks when the thread is in the C0.2 light-weight faster wakeup time but less power saving optimized state.", + "EventCode": "0xec", + "EventName": "CPU_CLK_UNHALTED.C02", + "PublicDescription": "Counts core clocks when the thread is in the C0.2 light-weight faster wakeup time but less power saving optimized state. This state can be entered via the TPAUSE or UMWAIT instructions.", + "SampleAfterValue": "2000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Core clocks when the thread is in the C0.1 or C0.2 or running a PAUSE in C0 ACPI state.", + "EventCode": "0xec", + "EventName": "CPU_CLK_UNHALTED.C0_WAIT", + "PublicDescription": "Counts core clocks when the thread is in the C0.1 or C0.2 power saving optimized states (TPAUSE or UMWAIT instructions) or running the PAUSE instruction.", + "SampleAfterValue": "2000003", + "UMask": "0x70" + }, + { + "BriefDescription": "Cycle counts are evenly distributed between active threads in the Core.", + "EventCode": "0xec", + "EventName": "CPU_CLK_UNHALTED.DISTRIBUTED", + "PublicDescription": "This event distributes cycle counts between active hyperthreads, i.e., those in C0. A hyperthread becomes inactive when it executes the HLT or MWAIT instructions. If all other hyperthreads are inactive (or disabled or do not exist), all counts are attributed to this hyperthread. To obtain the full count when the Core is active, sum the counts from each hyperthread.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Core crystal clock cycles when this thread is unhalted and the other thread is halted.", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE", + "PublicDescription": "Counts Core crystal clock cycles when current thread is unhalted and the other thread is halted.", + "SampleAfterValue": "25003", + "UMask": "0x2" + }, + { + "BriefDescription": "CPU_CLK_UNHALTED.PAUSE", + "EventCode": "0xec", + "EventName": "CPU_CLK_UNHALTED.PAUSE", + "SampleAfterValue": "2000003", + "UMask": "0x40" + }, + { + "BriefDescription": "CPU_CLK_UNHALTED.PAUSE_INST", + "CounterMask": "1", + "EdgeDetect": "1", + "EventCode": "0xec", + "EventName": "CPU_CLK_UNHALTED.PAUSE_INST", + "SampleAfterValue": "2000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Core crystal clock cycles. Cycle counts are evenly distributed between active threads in the Core.", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.REF_DISTRIBUTED", + "PublicDescription": "This event distributes Core crystal clock cycle counts between active hyperthreads, i.e., those in C0 sleep-state. A hyperthread becomes inactive when it executes the HLT or MWAIT instructions. If one thread is active in a core, all counts are attributed to this hyperthread. To obtain the full count when the Core is active, sum the counts from each hyperthread.", + "SampleAfterValue": "2000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Reference cycles when the core is not in halt state.", + "EventName": "CPU_CLK_UNHALTED.REF_TSC", + "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. It is counted on a dedicated fixed counter, leaving the eight programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.", + "SampleAfterValue": "2000003", + "UMask": "0x3" + }, + { + "BriefDescription": "Reference cycles when the core is not in halt state.", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.REF_TSC_P", + "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. It is counted on a dedicated fixed counter, leaving the four (eight when Hyperthreading is disabled) programmable counters available for other events. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Core cycles when the thread is not in halt state", + "EventName": "CPU_CLK_UNHALTED.THREAD", + "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the eight programmable counters available for other events.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Thread cycles when thread is not in halt state", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.THREAD_P", + "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.", + "SampleAfterValue": "2000003" + }, + { + "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.", + "CounterMask": "8", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.CYCLES_L1D_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Cycles while L2 cache miss demand load is outstanding.", + "CounterMask": "1", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.CYCLES_L2_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles while memory subsystem has an outstanding load.", + "CounterMask": "16", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.CYCLES_MEM_ANY", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.", + "CounterMask": "12", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.STALLS_L1D_MISS", + "SampleAfterValue": "1000003", + "UMask": "0xc" + }, + { + "BriefDescription": "Execution stalls while L2 cache miss demand load is outstanding.", + "CounterMask": "5", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.STALLS_L2_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x5" + }, + { + "BriefDescription": "Total execution stalls.", + "CounterMask": "4", + "EventCode": "0xa3", + "EventName": "CYCLE_ACTIVITY.STALLS_TOTAL", + "SampleAfterValue": "1000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Cycles total of 1 uop is executed on all ports and Reservation Station was not empty.", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.1_PORTS_UTIL", + "PublicDescription": "Counts cycles during which a total of 1 uop was executed on all ports and Reservation Station (RS) was not empty.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles total of 2 uops are executed on all ports and Reservation Station was not empty.", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.2_PORTS_UTIL", + "PublicDescription": "Counts cycles during which a total of 2 uops were executed on all ports and Reservation Station (RS) was not empty.", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station was not empty.", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.3_PORTS_UTIL", + "PublicDescription": "Cycles total of 3 uops are executed on all ports and Reservation Station (RS) was not empty.", + "SampleAfterValue": "2000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station was not empty.", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.4_PORTS_UTIL", + "PublicDescription": "Cycles total of 4 uops are executed on all ports and Reservation Station (RS) was not empty.", + "SampleAfterValue": "2000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Execution stalls while memory subsystem has an outstanding load.", + "CounterMask": "5", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.BOUND_ON_LOADS", + "SampleAfterValue": "2000003", + "UMask": "0x21" + }, + { + "BriefDescription": "Cycles where the Store Buffer was full and no loads caused an execution stall.", + "CounterMask": "2", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.BOUND_ON_STORES", + "PublicDescription": "Counts cycles where the Store Buffer was full and no loads caused an execution stall.", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Cycles no uop executed while RS was not empty, the SB was not full and there was no outstanding load.", + "EventCode": "0xa6", + "EventName": "EXE_ACTIVITY.EXE_BOUND_0_PORTS", + "PublicDescription": "Number of cycles total of 0 uops executed on all ports, Reservation Station (RS) was not empty, the Store Buffer (SB) was not full and there was no outstanding load.", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Instruction decoders utilized in a cycle", + "EventCode": "0x75", + "EventName": "INST_DECODED.DECODERS", + "PublicDescription": "Number of decoders utilized in a cycle when the MITE (legacy decode pipeline) fetches instructions.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of instructions retired. Fixed Counter - architectural event", + "EventName": "INST_RETIRED.ANY", + "PEBS": "1", + "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of instructions retired. General Counter - architectural event", + "EventCode": "0xc0", + "EventName": "INST_RETIRED.ANY_P", + "PEBS": "1", + "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.", + "SampleAfterValue": "2000003" + }, + { + "BriefDescription": "INST_RETIRED.MACRO_FUSED", + "EventCode": "0xc0", + "EventName": "INST_RETIRED.MACRO_FUSED", + "SampleAfterValue": "2000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Retired NOP instructions.", + "EventCode": "0xc0", + "EventName": "INST_RETIRED.NOP", + "PublicDescription": "Counts all retired NOP or ENDBR32/64 instructions", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Precise instruction retired with PEBS precise-distribution", + "EventName": "INST_RETIRED.PREC_DIST", + "PEBS": "1", + "PublicDescription": "A version of INST_RETIRED that allows for a precise distribution of samples across instructions retired. It utilizes the Precise Distribution of Instructions Retired (PDIR++) feature to fix bias in how retired instructions get sampled. Use on Fixed Counter 0.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Iterations of Repeat string retired instructions.", + "EventCode": "0xc0", + "EventName": "INST_RETIRED.REP_ITERATION", + "PublicDescription": "Number of iterations of Repeat (REP) string retired instructions such as MOVS, CMPS, and SCAS. Each has a byte, word, and doubleword version and string instructions can be repeated using a repetition prefix, REP, that allows their architectural execution to be repeated a number of times as specified by the RCX register. Note the number of iterations is implementation-dependent.", + "SampleAfterValue": "2000003", + "UMask": "0x8" + }, + { + "BriefDescription": "Clears speculative count", + "CounterMask": "1", + "EdgeDetect": "1", + "EventCode": "0xad", + "EventName": "INT_MISC.CLEARS_COUNT", + "PublicDescription": "Counts the number of speculative clears due to any type of branch misprediction or machine clears", + "SampleAfterValue": "500009", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path.", + "EventCode": "0xad", + "EventName": "INT_MISC.CLEAR_RESTEER_CYCLES", + "PublicDescription": "Cycles after recovery from a branch misprediction or machine clear till the first uop is issued from the resteered path.", + "SampleAfterValue": "500009", + "UMask": "0x80" + }, + { + "BriefDescription": "INT_MISC.MBA_STALLS", + "EventCode": "0xad", + "EventName": "INT_MISC.MBA_STALLS", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Core cycles the allocator was stalled due to recovery from earlier clear event for this thread", + "EventCode": "0xad", + "EventName": "INT_MISC.RECOVERY_CYCLES", + "PublicDescription": "Counts core cycles when the Resource allocator was stalled due to recovery from an earlier branch misprediction or machine clear event.", + "SampleAfterValue": "500009", + "UMask": "0x1" + }, + { + "BriefDescription": "INT_MISC.UNKNOWN_BRANCH_CYCLES", + "EventCode": "0xad", + "EventName": "INT_MISC.UNKNOWN_BRANCH_CYCLES", + "MSRIndex": "0x3F7", + "MSRValue": "0x7", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "TMA slots where uops got dropped", + "EventCode": "0xad", + "EventName": "INT_MISC.UOP_DROPPING", + "PublicDescription": "Estimated number of Top-down Microarchitecture Analysis slots that got dropped due to non front-end reasons", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "INT_VEC_RETIRED.128BIT", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.128BIT", + "SampleAfterValue": "1000003", + "UMask": "0x13" + }, + { + "BriefDescription": "INT_VEC_RETIRED.256BIT", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.256BIT", + "SampleAfterValue": "1000003", + "UMask": "0xac" + }, + { + "BriefDescription": "integer ADD, SUB, SAD 128-bit vector instructions.", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.ADD_128", + "PublicDescription": "Number of retired integer ADD/SUB (regular or horizontal), SAD 128-bit vector instructions.", + "SampleAfterValue": "1000003", + "UMask": "0x3" + }, + { + "BriefDescription": "integer ADD, SUB, SAD 256-bit vector instructions.", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.ADD_256", + "PublicDescription": "Number of retired integer ADD/SUB (regular or horizontal), SAD 256-bit vector instructions.", + "SampleAfterValue": "1000003", + "UMask": "0xc" + }, + { + "BriefDescription": "INT_VEC_RETIRED.MUL_256", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.MUL_256", + "SampleAfterValue": "1000003", + "UMask": "0x80" + }, + { + "BriefDescription": "INT_VEC_RETIRED.SHUFFLES", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.SHUFFLES", + "SampleAfterValue": "1000003", + "UMask": "0x40" + }, + { + "BriefDescription": "INT_VEC_RETIRED.VNNI_128", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.VNNI_128", + "SampleAfterValue": "1000003", + "UMask": "0x10" + }, + { + "BriefDescription": "INT_VEC_RETIRED.VNNI_256", + "EventCode": "0xe7", + "EventName": "INT_VEC_RETIRED.VNNI_256", + "SampleAfterValue": "1000003", + "UMask": "0x20" + }, + { + "BriefDescription": "False dependencies in MOB due to partial compare on address.", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.ADDRESS_ALIAS", + "PublicDescription": "Counts the number of times a load got blocked due to false dependencies in MOB due to partial compare on address.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "The number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.NO_SR", + "PublicDescription": "Counts the number of times that split load operations are temporarily blocked because all resources for handling the split accesses are in use.", + "SampleAfterValue": "100003", + "UMask": "0x88" + }, + { + "BriefDescription": "Loads blocked due to overlapping with a preceding store that cannot be forwarded.", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.STORE_FORWARD", + "PublicDescription": "Counts the number of times where store forwarding was prevented for a load operation. The most common case is a load blocked due to the address of memory access (partially) overlapping with a preceding uncompleted store. Note: See the table of not supported store forwards in the Optimization Guide.", + "SampleAfterValue": "100003", + "UMask": "0x82" + }, + { + "BriefDescription": "Counts the number of demand load dispatches that hit L1D fill buffer (FB) allocated for software prefetch.", + "EventCode": "0x4c", + "EventName": "LOAD_HIT_PREFETCH.SWPF", + "PublicDescription": "Counts all not software-prefetch load dispatches that hit the fill buffer (FB) allocated for the software prefetch. It can also be incremented by some lock instructions. So it should only be used with profiling so that the locks can be excluded by ASM (Assembly File) inspection of the nearby instructions.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles Uops delivered by the LSD, but didn't come from the decoder.", + "CounterMask": "1", + "EventCode": "0xa8", + "EventName": "LSD.CYCLES_ACTIVE", + "PublicDescription": "Counts the cycles when at least one uop is delivered by the LSD (Loop-stream detector).", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles optimal number of Uops delivered by the LSD, but did not come from the decoder.", + "CounterMask": "6", + "EventCode": "0xa8", + "EventName": "LSD.CYCLES_OK", + "PublicDescription": "Counts the cycles when optimal number of uops is delivered by the LSD (Loop-stream detector).", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of Uops delivered by the LSD.", + "EventCode": "0xa8", + "EventName": "LSD.UOPS", + "PublicDescription": "Counts the number of uops delivered to the back-end by the LSD(Loop Stream Detector).", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Number of machine clears (nukes) of any type.", + "CounterMask": "1", + "EdgeDetect": "1", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.COUNT", + "PublicDescription": "Counts the number of machine clears (nukes) of any type.", + "SampleAfterValue": "100003", + "UMask": "0x1" + }, + { + "BriefDescription": "Self-modifying code (SMC) detected.", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.SMC", + "PublicDescription": "Counts self-modifying code (SMC) detected, which causes a machine clear.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "LFENCE instructions retired", + "EventCode": "0xe0", + "EventName": "MISC2_RETIRED.LFENCE", + "PublicDescription": "number of LFENCE retired instructions", + "SampleAfterValue": "400009", + "UMask": "0x20" + }, + { + "BriefDescription": "Increments whenever there is an update to the LBR array.", + "EventCode": "0xcc", + "EventName": "MISC_RETIRED.LBR_INSERTS", + "PublicDescription": "Increments when an entry is added to the Last Branch Record (LBR) array (or removed from the array in case of RETURNs in call stack mode). The event requires LBR enable via IA32_DEBUGCTL MSR and branch type selection via MSR_LBR_SELECT.", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Cycles stalled due to no store buffers available. (not including draining form sync).", + "EventCode": "0xa2", + "EventName": "RESOURCE_STALLS.SB", + "PublicDescription": "Counts allocation stall cycles caused by the store buffer (SB) being full. This counts cycles that the pipeline back-end blocked uop delivery from the front-end.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Counts cycles where the pipeline is stalled due to serializing operations.", + "EventCode": "0xa2", + "EventName": "RESOURCE_STALLS.SCOREBOARD", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "TMA slots where no uops were being issued due to lack of back-end resources.", + "EventCode": "0xa4", + "EventName": "TOPDOWN.BACKEND_BOUND_SLOTS", + "PublicDescription": "Number of slots in TMA method where no micro-operations were being issued from front-end to back-end of the machine due to lack of back-end resources.", + "SampleAfterValue": "10000003", + "UMask": "0x2" + }, + { + "BriefDescription": "TMA slots wasted due to incorrect speculations.", + "EventCode": "0xa4", + "EventName": "TOPDOWN.BAD_SPEC_SLOTS", + "PublicDescription": "Number of slots of TMA method that were wasted due to incorrect speculation. It covers all types of control-flow or data-related mis-speculations.", + "SampleAfterValue": "10000003", + "UMask": "0x4" + }, + { + "BriefDescription": "TMA slots wasted due to incorrect speculation by branch mispredictions", + "EventCode": "0xa4", + "EventName": "TOPDOWN.BR_MISPREDICT_SLOTS", + "PublicDescription": "Number of TMA slots that were wasted due to incorrect speculation by (any type of) branch mispredictions. This event estimates number of speculative operations that were issued but not retired as well as the out-of-order engine recovery past a branch misprediction.", + "SampleAfterValue": "10000003", + "UMask": "0x8" + }, + { + "BriefDescription": "TOPDOWN.MEMORY_BOUND_SLOTS", + "EventCode": "0xa4", + "EventName": "TOPDOWN.MEMORY_BOUND_SLOTS", + "SampleAfterValue": "10000003", + "UMask": "0x10" + }, + { + "BriefDescription": "TMA slots available for an unhalted logical processor. Fixed counter - architectural event", + "EventName": "TOPDOWN.SLOTS", + "PublicDescription": "Number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method (TMA). The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core. Software can use this event as the denominator for the top-level metrics of the TMA method. This architectural event is counted on a designated fixed counter (Fixed Counter 3).", + "SampleAfterValue": "10000003", + "UMask": "0x4" + }, + { + "BriefDescription": "TMA slots available for an unhalted logical processor. General counter - architectural event", + "EventCode": "0xa4", + "EventName": "TOPDOWN.SLOTS_P", + "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method. The count is distributed among unhalted logical processors (hyper-threads) who share the same physical core.", + "SampleAfterValue": "10000003", + "UMask": "0x1" + }, + { + "BriefDescription": "UOPS_DECODED.DEC0_UOPS", + "EventCode": "0x76", + "EventName": "UOPS_DECODED.DEC0_UOPS", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Uops executed on port 0", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_0", + "PublicDescription": "Number of uops dispatch to execution port 0.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Uops executed on port 1", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_1", + "PublicDescription": "Number of uops dispatch to execution port 1.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Uops executed on ports 2, 3 and 10", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_2_3_10", + "PublicDescription": "Number of uops dispatch to execution ports 2, 3 and 10", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Uops executed on ports 4 and 9", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_4_9", + "PublicDescription": "Number of uops dispatch to execution ports 4 and 9", + "SampleAfterValue": "2000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Uops executed on ports 5 and 11", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_5_11", + "PublicDescription": "Number of uops dispatch to execution ports 5 and 11", + "SampleAfterValue": "2000003", + "UMask": "0x20" + }, + { + "BriefDescription": "Uops executed on port 6", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_6", + "PublicDescription": "Number of uops dispatch to execution port 6.", + "SampleAfterValue": "2000003", + "UMask": "0x40" + }, + { + "BriefDescription": "Uops executed on ports 7 and 8", + "EventCode": "0xb2", + "EventName": "UOPS_DISPATCHED.PORT_7_8", + "PublicDescription": "Number of uops dispatch to execution ports 7 and 8.", + "SampleAfterValue": "2000003", + "UMask": "0x80" + }, + { + "BriefDescription": "Number of uops executed on the core.", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CORE", + "PublicDescription": "Counts the number of uops executed from any thread.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles at least 1 micro-op is executed from any thread on physical core.", + "CounterMask": "1", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_1", + "PublicDescription": "Counts cycles when at least 1 micro-op is executed from any thread on physical core.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles at least 2 micro-op is executed from any thread on physical core.", + "CounterMask": "2", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_2", + "PublicDescription": "Counts cycles when at least 2 micro-ops are executed from any thread on physical core.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles at least 3 micro-op is executed from any thread on physical core.", + "CounterMask": "3", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_3", + "PublicDescription": "Counts cycles when at least 3 micro-ops are executed from any thread on physical core.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles at least 4 micro-op is executed from any thread on physical core.", + "CounterMask": "4", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CORE_CYCLES_GE_4", + "PublicDescription": "Counts cycles when at least 4 micro-ops are executed from any thread on physical core.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles where at least 1 uop was executed per-thread", + "CounterMask": "1", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CYCLES_GE_1", + "PublicDescription": "Cycles where at least 1 uop was executed per-thread.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles where at least 2 uops were executed per-thread", + "CounterMask": "2", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CYCLES_GE_2", + "PublicDescription": "Cycles where at least 2 uops were executed per-thread.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles where at least 3 uops were executed per-thread", + "CounterMask": "3", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CYCLES_GE_3", + "PublicDescription": "Cycles where at least 3 uops were executed per-thread.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles where at least 4 uops were executed per-thread", + "CounterMask": "4", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.CYCLES_GE_4", + "PublicDescription": "Cycles where at least 4 uops were executed per-thread.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts number of cycles no uops were dispatched to be executed on this thread.", + "CounterMask": "1", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.STALLS", + "Invert": "1", + "PublicDescription": "Counts cycles during which no uops were dispatched from the Reservation Station (RS) per thread.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event UOPS_EXECUTED.STALLS", + "CounterMask": "1", + "Deprecated": "1", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.STALL_CYCLES", + "Invert": "1", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of uops to be executed per-thread each cycle.", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.THREAD", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Counts the number of x87 uops dispatched.", + "EventCode": "0xb1", + "EventName": "UOPS_EXECUTED.X87", + "PublicDescription": "Counts the number of x87 uops executed.", + "SampleAfterValue": "2000003", + "UMask": "0x10" + }, + { + "BriefDescription": "Uops that RAT issues to RS", + "EventCode": "0xae", + "EventName": "UOPS_ISSUED.ANY", + "PublicDescription": "Counts the number of uops that the Resource Allocation Table (RAT) issues to the Reservation Station (RS).", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles with retired uop(s).", + "CounterMask": "1", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.CYCLES", + "PublicDescription": "Counts cycles where at least one uop has retired.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Retired uops except the last uop of each instruction.", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.HEAVY", + "PublicDescription": "Counts the number of retired micro-operations (uops) except the last uop of each instruction. An instruction that is decoded into less than two uops does not contribute to the count.", + "SampleAfterValue": "2000003", + "UMask": "0x1" + }, + { + "BriefDescription": "UOPS_RETIRED.MS", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.MS", + "MSRIndex": "0x3F7", + "MSRValue": "0x8", + "SampleAfterValue": "2000003", + "UMask": "0x4" + }, + { + "BriefDescription": "Retirement slots used.", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.SLOTS", + "PublicDescription": "Counts the retirement slots used each cycle.", + "SampleAfterValue": "2000003", + "UMask": "0x2" + }, + { + "BriefDescription": "Cycles without actually retired uops.", + "CounterMask": "1", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.STALLS", + "Invert": "1", + "PublicDescription": "This event counts cycles without actually retired uops.", + "SampleAfterValue": "1000003", + "UMask": "0x2" + }, + { + "BriefDescription": "This event is deprecated. Refer to new event UOPS_RETIRED.STALLS", + "CounterMask": "1", + "Deprecated": "1", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.STALL_CYCLES", + "Invert": "1", + "SampleAfterValue": "1000003", + "UMask": "0x2" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cache.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cache.json new file mode 100644 index 000000000000..bf5a511b99d1 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cache.json @@ -0,0 +1,5988 @@ +[ + { + "BriefDescription": "CHA to iMC Bypass : Intermediate bypass Taken", + "EventCode": "0x57", + "EventName": "UNC_CHA_BYPASS_CHA_IMC.INTERMEDIATE", + "PerPkg": "1", + "PublicDescription": "CHA to iMC Bypass : Intermediate bypass Taken : Counts the number of times when the CHA was able to bypass HA pipe on the way to iMC. This is a latency optimization for situations when there is light loadings on the memory subsystem. This can be filtered by when the bypass was taken and when it was not. : Filter for transactions that succeeded in taking the intermediate bypass.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Bypass : Not Taken", + "EventCode": "0x57", + "EventName": "UNC_CHA_BYPASS_CHA_IMC.NOT_TAKEN", + "PerPkg": "1", + "PublicDescription": "CHA to iMC Bypass : Not Taken : Counts the number of times when the CHA was able to bypass HA pipe on the way to iMC. This is a latency optimization for situations when there is light loadings on the memory subsystem. This can be filtered by when the bypass was taken and when it was not. : Filter for transactions that could not take the bypass, and issues a read to memory. Note that transactions that did not take the bypass but did not issue read to memory will not be counted.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Bypass : Taken", + "EventCode": "0x57", + "EventName": "UNC_CHA_BYPASS_CHA_IMC.TAKEN", + "PerPkg": "1", + "PublicDescription": "CHA to iMC Bypass : Taken : Counts the number of times when the CHA was able to bypass HA pipe on the way to iMC. This is a latency optimization for situations when there is light loadings on the memory subsystem. This can be filtered by when the bypass was taken and when it was not. : Filter for transactions that succeeded in taking the full bypass.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA Clockticks", + "EventCode": "0x01", + "EventName": "UNC_CHA_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of CHA clock cycles while the event is enabled", + "Unit": "CHA" + }, + { + "BriefDescription": "CMS Clockticks", + "EventCode": "0xc0", + "EventName": "UNC_CHA_CMS_CLOCKTICKS", + "PerPkg": "1", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Any Cycle with Multiple Snoops", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.ANY_GTONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Any Cycle with Multiple Snoops : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0xf2", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Any Single Snoop", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.ANY_ONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Any Single Snoop : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0xf1", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Multiple Core Requests", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.CORE_GTONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Multiple Core Requests : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x42", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Single Core Requests", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.CORE_ONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Single Core Requests : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x41", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Multiple Eviction", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.EVICT_GTONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Multiple Eviction : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x82", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Single Eviction", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.EVICT_ONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Single Eviction : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x81", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Multiple External Snoops", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.EXT_GTONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Multiple External Snoops : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x22", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Single External Snoops", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.EXT_ONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Single External Snoops : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x21", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Multiple Snoop Targets from Remote", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.REMOTE_GTONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Multiple Snoop Targets from Remote : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x12", + "Unit": "CHA" + }, + { + "BriefDescription": "Core Cross Snoops Issued : Single Snoop Target from Remote", + "EventCode": "0x33", + "EventName": "UNC_CHA_CORE_SNP.REMOTE_ONE", + "PerPkg": "1", + "PublicDescription": "Core Cross Snoops Issued : Single Snoop Target from Remote : Counts the number of transactions that trigger a configurable number of cross snoops. Cores are snooped if the transaction looks up the cache and determines that it is necessary based on the operation type and what CoreValid bits are set. For example, if 2 CV bits are set on a data read, the cores must have the data in S state so it is not necessary to snoop them. However, if only 1 CV bit is set the core my have modified the data. If the transaction was an RFO, it would need to invalidate the lines. This event can be filtered based on who triggered the initial snoop(s).", + "UMask": "0x11", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6e", + "EventName": "UNC_CHA_DIRECT_GO.HA_SUPPRESS_DRD", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6e", + "EventName": "UNC_CHA_DIRECT_GO.HA_SUPPRESS_NO_D2C", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6e", + "EventName": "UNC_CHA_DIRECT_GO.HA_TOR_DEALLOC", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.EXTCMP", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.FAST_GO", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.FAST_GO_PULL", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.GO", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.GO_PULL", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.IDLE_DUE_SUPPRESS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.NOP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Direct GO", + "EventCode": "0x6d", + "EventName": "UNC_CHA_DIRECT_GO_OPC.PULL", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Multi-socket cacheline Directory state lookups; Snoop Not Needed", + "EventCode": "0x53", + "EventName": "UNC_CHA_DIR_LOOKUP.NO_SNP", + "PerPkg": "1", + "PublicDescription": "Counts transactions that looked into the multi-socket cacheline Directory state, and therefore did not send a snoop because the Directory indicated it was not needed.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Multi-socket cacheline Directory state lookups; Snoop Needed", + "EventCode": "0x53", + "EventName": "UNC_CHA_DIR_LOOKUP.SNP", + "PerPkg": "1", + "PublicDescription": "Counts transactions that looked into the multi-socket cacheline Directory state, and sent one or more snoops, because the Directory indicated it was needed.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Multi-socket cacheline Directory state updates; Directory Updated memory write from the HA pipe", + "EventCode": "0x54", + "EventName": "UNC_CHA_DIR_UPDATE.HA", + "PerPkg": "1", + "PublicDescription": "Counts only multi-socket cacheline Directory state updates memory writes issued from the HA pipe. This does not include memory write requests which are for I (Invalid) or E (Exclusive) cachelines.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Multi-socket cacheline Directory state updates; Directory Updated memory write from TOR pipe", + "EventCode": "0x54", + "EventName": "UNC_CHA_DIR_UPDATE.TOR", + "PerPkg": "1", + "PublicDescription": "Counts only multi-socket cacheline Directory state updates due to memory writes issued from the TOR pipe which are the result of remote transaction hitting the SF/LLC and returning data Core2Core. This does not include memory write requests which are for I (Invalid) or E (Exclusive) cachelines.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Down", + "EventCode": "0xba", + "EventName": "UNC_CHA_EGRESS_ORDERING.IV_SNOOPGO_DN", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Down : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Up", + "EventCode": "0xba", + "EventName": "UNC_CHA_EGRESS_ORDERING.IV_SNOOPGO_UP", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Up : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Read request from a remote socket which hit in the HitMe Cache to a line In the E state", + "EventCode": "0x5f", + "EventName": "UNC_CHA_HITME_HIT.EX_RDS", + "PerPkg": "1", + "PublicDescription": "Counts read requests from a remote socket which hit in the HitME cache (used to cache the multi-socket Directory state) to a line in the E(Exclusive) state. This includes the following read opcodes (RdCode, RdData, RdDataMigratory, RdCur, RdInv*, Inv*).", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of Hits in HitMe Cache : Shared hit and op is RdInvOwn, RdInv, Inv*", + "EventCode": "0x5f", + "EventName": "UNC_CHA_HITME_HIT.SHARED_OWNREQ", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of Hits in HitMe Cache : op is WbMtoE", + "EventCode": "0x5f", + "EventName": "UNC_CHA_HITME_HIT.WBMTOE", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of Hits in HitMe Cache : op is WbMtoI, WbPushMtoI, WbFlush, or WbMtoS", + "EventCode": "0x5f", + "EventName": "UNC_CHA_HITME_HIT.WBMTOI_OR_S", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of times HitMe Cache is accessed : op is RdCode, RdData, RdDataMigratory, RdCur, RdInvOwn, RdInv, Inv*", + "EventCode": "0x5e", + "EventName": "UNC_CHA_HITME_LOOKUP.READ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of times HitMe Cache is accessed : op is WbMtoE, WbMtoI, WbPushMtoI, WbFlush, or WbMtoS", + "EventCode": "0x5e", + "EventName": "UNC_CHA_HITME_LOOKUP.WRITE", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of Misses in HitMe Cache : No SF/LLC HitS/F and op is RdInvOwn", + "EventCode": "0x60", + "EventName": "UNC_CHA_HITME_MISS.NOTSHARED_RDINVOWN", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of Misses in HitMe Cache : op is RdCode, RdData, RdDataMigratory, RdCur, RdInv, Inv*", + "EventCode": "0x60", + "EventName": "UNC_CHA_HITME_MISS.READ_OR_INV", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts Number of Misses in HitMe Cache : SF/LLC HitS/F and op is RdInvOwn", + "EventCode": "0x60", + "EventName": "UNC_CHA_HITME_MISS.SHARED_RDINVOWN", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of Allocate/Update to HitMe Cache : Deallocate HitME$ on Reads without RspFwdI*", + "EventCode": "0x61", + "EventName": "UNC_CHA_HITME_UPDATE.DEALLOCATE", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of Allocate/Update to HitMe Cache : op is RspIFwd or RspIFwdWb for a local request", + "EventCode": "0x61", + "EventName": "UNC_CHA_HITME_UPDATE.DEALLOCATE_RSPFWDI_LOC", + "PerPkg": "1", + "PublicDescription": "Counts the number of Allocate/Update to HitMe Cache : op is RspIFwd or RspIFwdWb for a local request : Received RspFwdI* for a local request, but converted HitME$ to SF entry", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of Allocate/Update to HitMe Cache : Update HitMe Cache on RdInvOwn even if not RspFwdI*", + "EventCode": "0x61", + "EventName": "UNC_CHA_HITME_UPDATE.RDINVOWN", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of Allocate/Update to HitMe Cache : op is RspIFwd or RspIFwdWb for a remote request", + "EventCode": "0x61", + "EventName": "UNC_CHA_HITME_UPDATE.RSPFWDI_REM", + "PerPkg": "1", + "PublicDescription": "Counts the number of Allocate/Update to HitMe Cache : op is RspIFwd or RspIFwdWb for a remote request : Updated HitME$ on RspFwdI* or local HitM/E received for a remote request", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Counts the number of Allocate/Update to HitMe Cache : Update HitMe Cache to SHARed", + "EventCode": "0x61", + "EventName": "UNC_CHA_HITME_UPDATE.SHARED", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Normal priority reads issued to the memory controller from the CHA", + "EventCode": "0x59", + "EventName": "UNC_CHA_IMC_READS_COUNT.NORMAL", + "PerPkg": "1", + "PublicDescription": "Counts when a normal (Non-Isochronous) read is issued to any of the memory controller channels from the CHA.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "HA to iMC Reads Issued : ISOCH", + "EventCode": "0x59", + "EventName": "UNC_CHA_IMC_READS_COUNT.PRIORITY", + "PerPkg": "1", + "PublicDescription": "HA to iMC Reads Issued : ISOCH : Count of the number of reads issued to any of the memory controller channels. This can be filtered by the priority of the reads.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued; Full Line Non-ISOCH", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.FULL", + "PerPkg": "1", + "PublicDescription": "Counts when a normal (Non-Isochronous) full line write is issued from the CHA to the any of the memory controller channels.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued : ISOCH Full Line", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.FULL_PRIORITY", + "PerPkg": "1", + "PublicDescription": "CHA to iMC Full Line Writes Issued : ISOCH Full Line : Counts the total number of full line writes issued from the HA into the memory controller.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued : Partial Non-ISOCH", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.PARTIAL", + "PerPkg": "1", + "PublicDescription": "CHA to iMC Full Line Writes Issued : Partial Non-ISOCH : Counts the total number of full line writes issued from the HA into the memory controller.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA to iMC Full Line Writes Issued : ISOCH Partial", + "EventCode": "0x5b", + "EventName": "UNC_CHA_IMC_WRITES_COUNT.PARTIAL_PRIORITY", + "PerPkg": "1", + "PublicDescription": "CHA to iMC Full Line Writes Issued : ISOCH Partial : Counts the total number of full line writes issued from the HA into the memory controller.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Any Request", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.ALL", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state.; Filters for any transaction originating from the IPQ or IRQ. This does not include lookups originating from the ISMQ.", + "UMask": "0x1fffff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : All transactions from Remote Agents", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.ALL_REMOTE", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : All transactions from Remote Agents : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x17e0ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : All Requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.ANY_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : All Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Any local or remote transaction to the LLC, including prefetch.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : CRd Requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.CODE", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote CRd transactions to the LLC. This includes CRd prefetch.", + "UMask": "0x1bd0ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : CRd Requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.CODE_READ_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote CRd transactions to the LLC. This includes CRd prefetch.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Local non-prefetch requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.COREPREF_OR_DMND_LOCAL_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Local non-prefetch requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Any local transaction to the LLC, not including prefetch", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Data Read Request", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1bc1ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Data Reads", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_ALL", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Data Reads : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x1fc1ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Data Read Request", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Data Read Request : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Read transactions.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Demand Data Reads, Core and LLC prefetches", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_LOCAL", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Demand Data Reads, Core and LLC prefetches : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x841ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Data Read Misses", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.DATA_READ_MISS", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Data Read Misses : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x1fc101", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : E State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.E", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : E State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Hit Exclusive State", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : F State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : F State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Hit Forward State", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Flush or Invalidate Requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.FLUSH_INV", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Flush : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing.", + "UMask": "0x1a44ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Flush", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.FLUSH_OR_INV_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Flush : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : I State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.I", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : I State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Miss", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Local LLC prefetch requests (from LLC)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LLCPREF_LOCAL_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Local LLC prefetch requests (from LLC) : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Any local LLC prefetch to the LLC", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Transactions homed locally", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCALLY_HOMED_ADDRESS", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Transactions homed locally : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Transaction whose address resides in the local MC.", + "UMask": "0xbdfff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : CRd Requests that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_CODE", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote CRd transactions to the LLC. This includes CRd prefetch.", + "UMask": "0x19d0ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Data Read Request that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DATA_RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x19c1ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Demand CRd Requests that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DMND_CODE", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote CRd transactions to the LLC. This includes CRd prefetch.", + "UMask": "0x1850ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Demand Data Reads that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DMND_DATA_RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1841ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Demand RFO Requests that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_DMND_RFO", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote RFO transactions to the LLC. This includes RFO prefetch.", + "UMask": "0x1848ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Transactions homed locally", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Transactions homed locally : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Transaction whose address resides in the local MC.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Flush or Invalidate Requests that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_FLUSH_INV", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Flush : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing.", + "UMask": "0x1844ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Prefetch requests to the LLC that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_LLC_PF", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x189dff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Data Read Prefetches that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x199dff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : CRd Prefetches that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF_CODE", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote CRd transactions to the LLC. This includes CRd prefetch.", + "UMask": "0x1910ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Data Read Prefetches that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF_DATA_RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1981ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : RFO Prefetches that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_PF_RFO", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote RFO transactions to the LLC. This includes RFO prefetch.", + "UMask": "0x1908ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : RFO Requests that come from the local socket (usually the core)", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.LOCAL_RFO", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote RFO transactions to the LLC. This includes RFO prefetch.", + "UMask": "0x19c8ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : M State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.M", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : M State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Hit Modified State", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : All Misses", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.MISS_ALL", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x1fe001", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Write Requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.OTHER_REQ_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Write Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Writeback transactions from L2 to the LLC This includes all write transactions -- both Cacheable and UC.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Remote non-snoop requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.PREF_OR_DMND_REMOTE_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Remote non-snoop requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Remote non-snoop transactions to the LLC.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Transactions homed remotely", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTELY_HOMED_ADDRESS", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Transactions homed remotely : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Transaction whose address resides in a remote MC", + "UMask": "0x15dfff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : CRd Requests that come from a Remote socket.", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_CODE", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : CRd Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote CRd transactions to the LLC. This includes CRd prefetch.", + "UMask": "0x1a10ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Data Read Requests that come from a Remote socket", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_DATA_RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state. Read transactions", + "UMask": "0x1a01ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Transactions homed remotely", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Transactions homed remotely : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Transaction whose address resides in a remote MC", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Flush or Invalidate requests that come from a Remote socket.", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_FLUSH_INV", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Flush : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing.", + "UMask": "0x1a04ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Filters Requests for those that write info into the cache that come from a remote socket", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_OTHER", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Write Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Writeback transactions from L2 to the LLC This includes all write transactions -- both Cacheable and UC.", + "UMask": "0x1a02ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : RFO Requests that come from a Remote socket.", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_RFO", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote RFO transactions to the LLC. This includes RFO prefetch.", + "UMask": "0x1a08ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Remote snoop requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_SNOOP_F", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : Remote snoop requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Remote snoop transactions to the LLC.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache and Snoop Filter Lookups; Snoop Requests from a Remote Socket", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.REMOTE_SNP", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. CHAFilter0[24:21,17] bits correspond to [FMESI] state.; Filters for any transaction originating from the IPQ or IRQ. This does not include lookups originating from the ISMQ.", + "UMask": "0x1c19ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : RFO Requests", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.RFO", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : RFO Requests : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Local or remote RFO transactions to the LLC. This includes RFO prefetch.", + "UMask": "0x1bc8ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : RFO Request Filter", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.RFO_F", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing. : Local or remote RFO transactions to the LLC. This includes RFO prefetch.", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Locally HOMed RFOs - Demand and Prefetches", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.RFO_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x9c8ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : S State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.S", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : S State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : Hit Shared State", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : SnoopFilter - E State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.SF_E", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : SnoopFilter - E State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : SF Hit Exclusive State", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : SnoopFilter - H State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.SF_H", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : SnoopFilter - H State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : SF Hit HitMe State", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : SnoopFilter - S State", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.SF_S", + "PerPkg": "1", + "PublicDescription": "Cache Lookups : SnoopFilter - S State : Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS set umask bit 0 and select a state or states to match. Otherwise, the event will count nothing. : SF Hit Shared State", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Writes", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.WRITE_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing. : Requests that install or change a line in the LLC. Examples: Writebacks from Core L2's and UPI. Prefetches into the LLC.", + "UMask": "0x842ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Cache Lookups : Remote Writes", + "EventCode": "0x34", + "EventName": "UNC_CHA_LLC_LOOKUP.WRITE_REMOTE", + "PerPkg": "1", + "PublicDescription": "Counts the number of times the LLC was accessed - this includes code, data, prefetches and hints coming from L2. This has numerous filters available. Note the non-standard filtering equation. This event will count requests that lookup the cache multiple times with multiple increments. One must ALWAYS select a state or states (in the umask field) to match. Otherwise, the event will count nothing.", + "UMask": "0x17c2ff", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Lines in E state", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.E_STATE", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Lines in E state : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : IA traffic", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IA", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : IA traffic : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : IO traffic", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IO", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : IO traffic : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in E state that are victimized on a fill from an IO device", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IO_E", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x12", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in F or S state that are victimized on a fill from an IO device", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IO_FS", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x1c", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in M state that are victimized on a fill from an IO device", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IO_M", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x11", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in any state that are victimized on a fill from an IO device", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.IO_MESF", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x1f", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized; Local - All Lines", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_ALL", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x200f", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_E", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x2002", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_M", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x2001", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Local Only", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_ONLY", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Local Only : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.LOCAL_S", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x2004", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Lines in M state", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.M_STATE", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Lines in M state : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized; Remote - All Lines", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_ALL", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x800f", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_E", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x8002", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_M", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x8001", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Remote Only", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_ONLY", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Remote Only : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.REMOTE_S", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x8004", + "Unit": "CHA" + }, + { + "BriefDescription": "Lines Victimized : Lines in S State", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.S_STATE", + "PerPkg": "1", + "PublicDescription": "Lines Victimized : Lines in S State : Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in E state that are victimized on a fill", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.TOTAL_E", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in M state that are victimized on a fill", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.TOTAL_M", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "All LLC lines in S state that are victimized on a fill", + "EventCode": "0x37", + "EventName": "UNC_CHA_LLC_VICTIMS.TOTAL_S", + "PerPkg": "1", + "PublicDescription": "Counts the number of lines that were victimized on a fill. This can be filtered by the state that the line was in.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Cbo Misc : CV0 Prefetch Miss", + "EventCode": "0x39", + "EventName": "UNC_CHA_MISC.CV0_PREF_MISS", + "PerPkg": "1", + "PublicDescription": "Cbo Misc : CV0 Prefetch Miss : Miscellaneous events in the Cbo.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Cbo Misc : CV0 Prefetch Victim", + "EventCode": "0x39", + "EventName": "UNC_CHA_MISC.CV0_PREF_VIC", + "PerPkg": "1", + "PublicDescription": "Cbo Misc : CV0 Prefetch Victim : Miscellaneous events in the Cbo.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Number of times that an RFO hit in S state.", + "EventCode": "0x39", + "EventName": "UNC_CHA_MISC.RFO_HIT_S", + "PerPkg": "1", + "PublicDescription": "Counts when a RFO (the Read for Ownership issued before a write) request hit a cacheline in the S (Shared) state.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Cbo Misc : Silent Snoop Eviction", + "EventCode": "0x39", + "EventName": "UNC_CHA_MISC.RSPI_WAS_FSE", + "PerPkg": "1", + "PublicDescription": "Cbo Misc : Silent Snoop Eviction : Miscellaneous events in the Cbo. : Counts the number of times when a Snoop hit in FSE states and triggered a silent eviction. This is useful because this information is lost in the PRE encodings.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Cbo Misc : Write Combining Aliasing", + "EventCode": "0x39", + "EventName": "UNC_CHA_MISC.WC_ALIASING", + "PerPkg": "1", + "PublicDescription": "Cbo Misc : Write Combining Aliasing : Miscellaneous events in the Cbo. : Counts the number of times that a USWC write (WCIL(F)) transaction hit in the LLC in M state, triggering a WBMtoI followed by the USWC write. This occurs when there is WC aliasing.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Local InvItoE", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.LOCAL_INVITOE", + "PerPkg": "1", + "PublicDescription": "OSB Snoop Broadcast : Local InvItoE : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Local Rd", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.LOCAL_READ", + "PerPkg": "1", + "PublicDescription": "OSB Snoop Broadcast : Local Rd : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Off", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.OFF_PWRHEURISTIC", + "PerPkg": "1", + "PublicDescription": "OSB Snoop Broadcast : Off : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Remote Rd", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.REMOTE_READ", + "PerPkg": "1", + "PublicDescription": "OSB Snoop Broadcast : Remote Rd : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : Remote Rd InvItoE", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.REMOTE_READINVITOE", + "PerPkg": "1", + "PublicDescription": "OSB Snoop Broadcast : Remote Rd InvItoE : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "OSB Snoop Broadcast : RFO HitS Snoop Broadcast", + "EventCode": "0x55", + "EventName": "UNC_CHA_OSB.RFO_HITS_SNP_BCAST", + "PerPkg": "1", + "PublicDescription": "OSB Snoop Broadcast : RFO HitS Snoop Broadcast : Count of OSB snoop broadcasts. Counts by 1 per request causing OSB snoops to be broadcast. Does not count all the snoops generated by OSB.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_MEMMODE_NM_INVITOX.LOCAL", + "EventCode": "0x65", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_INVITOX.LOCAL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_MEMMODE_NM_INVITOX.REMOTE", + "EventCode": "0x65", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_INVITOX.REMOTE", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_MEMMODE_NM_INVITOX.SETCONFLICT", + "EventCode": "0x65", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_INVITOX.SETCONFLICT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Memory Mode related events; Counts the number of times CHA saw a Near Memory set conflict in SF/LLC", + "EventCode": "0x64", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS.LLC", + "PerPkg": "1", + "PublicDescription": "Near Memory evictions due to another read to the same Near Memory set in the LLC.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Memory Mode related events; Counts the number of times CHA saw a Near memory set conflict in SF/LLC", + "EventCode": "0x64", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS.SF", + "PerPkg": "1", + "PublicDescription": "Near Memory evictions due to another read to the same Near Memory set in the SF", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Memory Mode related events; Counts the number of times CHA saw a Near Memory set conflict in TOR", + "EventCode": "0x64", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS.TOR", + "PerPkg": "1", + "PublicDescription": "No Reject in the CHA due to a pending read to the same Near Memory set in the TOR.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS2.IODC", + "EventCode": "0x70", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS2.IODC", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS2.MEMWR", + "EventCode": "0x70", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS2.MEMWR", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS2.MEMWRNI", + "EventCode": "0x70", + "EventName": "UNC_CHA_PMM_MEMMODE_NM_SETCONFLICTS2.MEMWRNI", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.DDR4_FAST_INSERT", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.DDR4_FAST_INSERT", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.REJ_IRQ", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.REJ_IRQ", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.SLOWTORQ_SKIP", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.SLOWTORQ_SKIP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.SLOW_INSERT", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.SLOW_INSERT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.THROTTLE", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.THROTTLE", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.THROTTLE_IRQ", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.THROTTLE_IRQ", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS.THROTTLE_PRQ", + "EventCode": "0x66", + "EventName": "UNC_CHA_PMM_QOS.THROTTLE_PRQ", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_PMM_QOS_OCCUPANCY.DDR_FAST_FIFO", + "EventCode": "0x67", + "EventName": "UNC_CHA_PMM_QOS_OCCUPANCY.DDR_FAST_FIFO", + "PerPkg": "1", + "PublicDescription": ": count # of FAST TOR Request inserted to ha_tor_req_fifo", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Number of SLOW TOR Request inserted to ha_pmm_tor_req_fifo", + "EventCode": "0x67", + "EventName": "UNC_CHA_PMM_QOS_OCCUPANCY.DDR_SLOW_FIFO", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx READ Credits Empty : MC0", + "EventCode": "0x58", + "EventName": "UNC_CHA_READ_NO_CREDITS.MC0", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx READ Credits Empty : MC0 : Counts the number of times when there are no credits available for sending reads from the CHA into the iMC. In order to send reads into the memory controller, the HA must first acquire a credit for the iMC's AD Ingress queue. : Filter for memory controller 0 only.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx READ Credits Empty : MC1", + "EventCode": "0x58", + "EventName": "UNC_CHA_READ_NO_CREDITS.MC1", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx READ Credits Empty : MC1 : Counts the number of times when there are no credits available for sending reads from the CHA into the iMC. In order to send reads into the memory controller, the HA must first acquire a credit for the iMC's AD Ingress queue. : Filter for memory controller 1 only.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx READ Credits Empty : MC2", + "EventCode": "0x58", + "EventName": "UNC_CHA_READ_NO_CREDITS.MC2", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx READ Credits Empty : MC2 : Counts the number of times when there are no credits available for sending reads from the CHA into the iMC. In order to send reads into the memory controller, the HA must first acquire a credit for the iMC's AD Ingress queue. : Filter for memory controller 2 only.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx READ Credits Empty : MC3", + "EventCode": "0x58", + "EventName": "UNC_CHA_READ_NO_CREDITS.MC3", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx READ Credits Empty : MC3 : Counts the number of times when there are no credits available for sending reads from the CHA into the iMC. In order to send reads into the memory controller, the HA must first acquire a credit for the iMC's AD Ingress queue. : Filter for memory controller 3 only.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx READ Credits Empty : MC4", + "EventCode": "0x58", + "EventName": "UNC_CHA_READ_NO_CREDITS.MC4", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx READ Credits Empty : MC4 : Counts the number of times when there are no credits available for sending reads from the CHA into the iMC. In order to send reads into the memory controller, the HA must first acquire a credit for the iMC's AD Ingress queue. : Filter for memory controller 4 only.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx READ Credits Empty : MC5", + "EventCode": "0x58", + "EventName": "UNC_CHA_READ_NO_CREDITS.MC5", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx READ Credits Empty : MC5 : Counts the number of times when there are no credits available for sending reads from the CHA into the iMC. In order to send reads into the memory controller, the HA must first acquire a credit for the iMC's AD Ingress queue. : Filter for memory controller 5 only.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Requests for exclusive ownership of a cache line without receiving data", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.INVITOE", + "PerPkg": "1", + "PublicDescription": "Counts the total number of requests coming from a unit on this socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.", + "UMask": "0x30", + "Unit": "CHA" + }, + { + "BriefDescription": "Local requests for exclusive ownership of a cache line without receiving data", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.INVITOE_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts the total number of requests coming from a unit on this socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Remote requests for exclusive ownership of a cache line without receiving data", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.INVITOE_REMOTE", + "PerPkg": "1", + "PublicDescription": "Counts the total number of requests coming from a remote socket for exclusive ownership of a cache line without receiving data (INVITOE) to the CHA.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Read requests made into the CHA", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.READS", + "PerPkg": "1", + "PublicDescription": "Counts read requests made into this CHA. Reads include all read opcodes (including RFO: the Read for Ownership issued before a write) .", + "UMask": "0x3", + "Unit": "CHA" + }, + { + "BriefDescription": "Read requests from a unit on this socket", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.READS_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts read requests coming from a unit on this socket made into this CHA. Reads include all read opcodes (including RFO: the Read for Ownership issued before a write).", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Read requests from a remote socket", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.READS_REMOTE", + "PerPkg": "1", + "PublicDescription": "Counts read requests coming from a remote socket made into the CHA. Reads include all read opcodes (including RFO: the Read for Ownership issued before a write).", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Write requests made into the CHA", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.WRITES", + "PerPkg": "1", + "PublicDescription": "Counts write requests made into the CHA, including streaming, evictions, HitM (Reads from another core to a Modified cacheline), etc.", + "UMask": "0xc", + "Unit": "CHA" + }, + { + "BriefDescription": "Write Requests from a unit on this socket", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.WRITES_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts write requests coming from a unit on this socket made into this CHA, including streaming, evictions, HitM (Reads from another core to a Modified cacheline), etc.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Read and Write Requests; Writes Remote", + "EventCode": "0x50", + "EventName": "UNC_CHA_REQUESTS.WRITES_REMOTE", + "PerPkg": "1", + "PublicDescription": "Counts the total number of read requests made into the Home Agent. Reads include all read opcodes (including RFO). Writes include all writes (streaming, evictions, HitM, etc).", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : IPQ", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.IPQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : IPQ : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : IRQ", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.IRQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : IRQ : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : IRQ Rejected", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.IRQ_REJ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : IRQ Rejected : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : PRQ", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.PRQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : PRQ : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : PRQ", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.PRQ_REJ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : PRQ : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : RRQ", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.RRQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : RRQ : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Allocations : WBQ", + "EventCode": "0x13", + "EventName": "UNC_CHA_RxC_INSERTS.WBQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Allocations : WBQ : Counts number of allocations per cycle into the specified Ingress queue.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : AD REQ on VN0", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : AD REQ on VN0 : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : AD RSP on VN0", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : AD RSP on VN0 : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : Non UPI AK Request", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : Non UPI AK Request : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL NCB on VN0", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL NCB on VN0 : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL NCS on VN0", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL NCS on VN0 : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL RSP on VN0", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL RSP on VN0 : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL WB on VN0", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : BL WB on VN0 : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 0 : Non UPI IV Request", + "EventCode": "0x22", + "EventName": "UNC_CHA_RxC_IPQ0_REJECT.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 0 : Non UPI IV Request : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : Allow Snoop", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.ALLOW_SNP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : ANY0", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.ANY0", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 1 : ANY0 : Any condition listed in the IPQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : HA", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.HA", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : LLC OR SF Way", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 1 : LLC OR SF Way : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : LLC Victim", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.LLC_VICTIM", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : PhyAddr Match", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.PA_MATCH", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 1 : PhyAddr Match : Address match with an outstanding request that was rejected.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : SF Victim", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "IPQ Requests (from CMS) Rejected - Set 1 : SF Victim : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "IPQ Requests (from CMS) Rejected - Set 1 : Victim", + "EventCode": "0x23", + "EventName": "UNC_CHA_RxC_IPQ1_REJECT.VICTIM", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : AD REQ on VN0", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : AD REQ on VN0 : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : AD RSP on VN0", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : AD RSP on VN0 : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : Non UPI AK Request", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : Non UPI AK Request : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL NCB on VN0", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL NCB on VN0 : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL NCS on VN0", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL NCS on VN0 : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL RSP on VN0", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL RSP on VN0 : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL WB on VN0", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : BL WB on VN0 : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 0 : Non UPI IV Request", + "EventCode": "0x18", + "EventName": "UNC_CHA_RxC_IRQ0_REJECT.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 0 : Non UPI IV Request : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : Allow Snoop", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.ALLOW_SNP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : ANY0", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.ANY0", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 1 : ANY0 : Any condition listed in the IRQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : HA", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.HA", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : LLC or SF Way", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 1 : LLC or SF Way : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : LLC Victim", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.LLC_VICTIM", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Request Queue Rejects; PhyAddr Match", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.PA_MATCH", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : SF Victim", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "IRQ Requests (from CMS) Rejected - Set 1 : SF Victim : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "IRQ Requests (from CMS) Rejected - Set 1 : Victim", + "EventCode": "0x19", + "EventName": "UNC_CHA_RxC_IRQ1_REJECT.VICTIM", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : AD REQ on VN0", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : AD REQ on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : AD RSP on VN0", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : AD RSP on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : Non UPI AK Request", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : Non UPI AK Request : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : BL NCB on VN0", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : BL NCB on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : BL NCS on VN0", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : BL NCS on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : BL RSP on VN0", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : BL RSP on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : BL WB on VN0", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : BL WB on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 0 : Non UPI IV Request", + "EventCode": "0x24", + "EventName": "UNC_CHA_RxC_ISMQ0_REJECT.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 0 : Non UPI IV Request : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : AD REQ on VN0", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : AD REQ on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : AD RSP on VN0", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : AD RSP on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : Non UPI AK Request", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : Non UPI AK Request : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : BL NCB on VN0", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : BL NCB on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : BL NCS on VN0", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : BL NCS on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : BL RSP on VN0", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : BL RSP on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : BL WB on VN0", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : BL WB on VN0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 0 : Non UPI IV Request", + "EventCode": "0x2c", + "EventName": "UNC_CHA_RxC_ISMQ0_RETRY.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 0 : Non UPI IV Request : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 1 : ANY0", + "EventCode": "0x25", + "EventName": "UNC_CHA_RxC_ISMQ1_REJECT.ANY0", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 1 : ANY0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : Any condition listed in the ISMQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Rejects - Set 1 : HA", + "EventCode": "0x25", + "EventName": "UNC_CHA_RxC_ISMQ1_REJECT.HA", + "PerPkg": "1", + "PublicDescription": "ISMQ Rejects - Set 1 : HA : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 1 : ANY0", + "EventCode": "0x2d", + "EventName": "UNC_CHA_RxC_ISMQ1_RETRY.ANY0", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 1 : ANY0 : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores. : Any condition listed in the ISMQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "ISMQ Retries - Set 1 : HA", + "EventCode": "0x2d", + "EventName": "UNC_CHA_RxC_ISMQ1_RETRY.HA", + "PerPkg": "1", + "PublicDescription": "ISMQ Retries - Set 1 : HA : Number of times a transaction flowing through the ISMQ had to retry. Transaction pass through the ISMQ as responses for requests that already exist in the Cbo. Some examples include: when data is returned or when snoop responses come back from the cores.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Occupancy : IPQ", + "EventCode": "0x11", + "EventName": "UNC_CHA_RxC_OCCUPANCY.IPQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Occupancy : IPQ : Counts number of entries in the specified Ingress queue in each cycle.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Occupancy : RRQ", + "EventCode": "0x11", + "EventName": "UNC_CHA_RxC_OCCUPANCY.RRQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Occupancy : RRQ : Counts number of entries in the specified Ingress queue in each cycle.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Ingress (from CMS) Occupancy : WBQ", + "EventCode": "0x11", + "EventName": "UNC_CHA_RxC_OCCUPANCY.WBQ", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Occupancy : WBQ : Counts number of entries in the specified Ingress queue in each cycle.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : AD REQ on VN0", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : AD REQ on VN0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : AD RSP on VN0", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : AD RSP on VN0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : Non UPI AK Request", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : Non UPI AK Request : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : BL NCB on VN0", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : BL NCB on VN0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : BL NCS on VN0", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : BL NCS on VN0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : BL RSP on VN0", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : BL RSP on VN0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : BL WB on VN0", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : BL WB on VN0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 0 : Non UPI IV Request", + "EventCode": "0x2e", + "EventName": "UNC_CHA_RxC_OTHER0_RETRY.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 0 : Non UPI IV Request : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : Allow Snoop", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.ALLOW_SNP", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : Allow Snoop : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject)", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : ANY0", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.ANY0", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : ANY0 : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : Any condition listed in the Other0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : HA", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.HA", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : HA : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject)", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : LLC OR SF Way", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : LLC OR SF Way : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : LLC Victim", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.LLC_VICTIM", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : LLC Victim : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject)", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : PhyAddr Match", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.PA_MATCH", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : PhyAddr Match : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : Address match with an outstanding request that was rejected.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : SF Victim", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : SF Victim : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject) : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Other Retries - Set 1 : Victim", + "EventCode": "0x2f", + "EventName": "UNC_CHA_RxC_OTHER1_RETRY.VICTIM", + "PerPkg": "1", + "PublicDescription": "Other Retries - Set 1 : Victim : Retry Queue Inserts of Transactions that were already in another Retry Q (sub-events encode the reason for the next reject)", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : AD REQ on VN0", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : AD REQ on VN0 : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : AD RSP on VN0", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : AD RSP on VN0 : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : Non UPI AK Request", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : Non UPI AK Request : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL NCB on VN0", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL NCB on VN0 : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL NCS on VN0", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL NCS on VN0 : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL RSP on VN0", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL RSP on VN0 : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL WB on VN0", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : BL WB on VN0 : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 0 : Non UPI IV Request", + "EventCode": "0x20", + "EventName": "UNC_CHA_RxC_PRQ0_REJECT.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 0 : Non UPI IV Request : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : Allow Snoop", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.ALLOW_SNP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : ANY0", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.ANY0", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 1 : ANY0 : Any condition listed in the PRQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : HA", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.HA", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : LLC OR SF Way", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 1 : LLC OR SF Way : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : LLC Victim", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.LLC_VICTIM", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : PhyAddr Match", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.PA_MATCH", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 1 : PhyAddr Match : Address match with an outstanding request that was rejected.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : SF Victim", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "PRQ Requests (from CMS) Rejected - Set 1 : SF Victim : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "PRQ Requests (from CMS) Rejected - Set 1 : Victim", + "EventCode": "0x21", + "EventName": "UNC_CHA_RxC_PRQ1_REJECT.VICTIM", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : AD REQ on VN0", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : AD REQ on VN0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : AD RSP on VN0", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : AD RSP on VN0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : Non UPI AK Request", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : Non UPI AK Request : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : BL NCB on VN0", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : BL NCB on VN0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : BL NCS on VN0", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : BL NCS on VN0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : BL RSP on VN0", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : BL RSP on VN0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : BL WB on VN0", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : BL WB on VN0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 0 : Non UPI IV Request", + "EventCode": "0x2a", + "EventName": "UNC_CHA_RxC_REQ_Q0_RETRY.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 0 : Non UPI IV Request : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : Allow Snoop", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.ALLOW_SNP", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : Allow Snoop : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : ANY0", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.ANY0", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : ANY0 : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : Any condition listed in the WBQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : HA", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.HA", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : HA : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : LLC OR SF Way", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : LLC OR SF Way : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : LLC Victim", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.LLC_VICTIM", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : LLC Victim : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : PhyAddr Match", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.PA_MATCH", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : PhyAddr Match : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : Address match with an outstanding request that was rejected.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : SF Victim", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : SF Victim : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ) : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Request Queue Retries - Set 1 : Victim", + "EventCode": "0x2b", + "EventName": "UNC_CHA_RxC_REQ_Q1_RETRY.VICTIM", + "PerPkg": "1", + "PublicDescription": "Request Queue Retries - Set 1 : Victim : REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : AD REQ on VN0", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : AD REQ on VN0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : AD RSP on VN0", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : AD RSP on VN0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : Non UPI AK Request", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : Non UPI AK Request : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : BL NCB on VN0", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : BL NCB on VN0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : BL NCS on VN0", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : BL NCS on VN0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : BL RSP on VN0", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : BL RSP on VN0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : BL WB on VN0", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : BL WB on VN0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 0 : Non UPI IV Request", + "EventCode": "0x26", + "EventName": "UNC_CHA_RxC_RRQ0_REJECT.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 0 : Non UPI IV Request : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : Allow Snoop", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.ALLOW_SNP", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : Allow Snoop : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : ANY0", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.ANY0", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : ANY0 : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : Any condition listed in the RRQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : HA", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.HA", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : HA : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : LLC OR SF Way", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : LLC OR SF Way : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : LLC Victim", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.LLC_VICTIM", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : LLC Victim : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : PhyAddr Match", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.PA_MATCH", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : PhyAddr Match : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : Address match with an outstanding request that was rejected.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : SF Victim", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : SF Victim : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry. : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "RRQ Rejects - Set 1 : Victim", + "EventCode": "0x27", + "EventName": "UNC_CHA_RxC_RRQ1_REJECT.VICTIM", + "PerPkg": "1", + "PublicDescription": "RRQ Rejects - Set 1 : Victim : Number of times a transaction flowing through the RRQ (Remote Response Queue) had to retry.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : AD REQ on VN0", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.AD_REQ_VN0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : AD REQ on VN0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : No AD VN0 credit for generating a request", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : AD RSP on VN0", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.AD_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : AD RSP on VN0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : No AD VN0 credit for generating a response", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : Non UPI AK Request", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.AK_NON_UPI", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : Non UPI AK Request : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : Can't inject AK ring message", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : BL NCB on VN0", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.BL_NCB_VN0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : BL NCB on VN0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : No BL VN0 credit for NCB", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : BL NCS on VN0", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.BL_NCS_VN0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : BL NCS on VN0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : No BL VN0 credit for NCS", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : BL RSP on VN0", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.BL_RSP_VN0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : BL RSP on VN0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : No BL VN0 credit for generating a response", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : BL WB on VN0", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.BL_WB_VN0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : BL WB on VN0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : No BL VN0 credit for generating a writeback", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 0 : Non UPI IV Request", + "EventCode": "0x28", + "EventName": "UNC_CHA_RxC_WBQ0_REJECT.IV_NON_UPI", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 0 : Non UPI IV Request : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : Can't inject IV ring message", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : Allow Snoop", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.ALLOW_SNP", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : Allow Snoop : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : ANY0", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.ANY0", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : ANY0 : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : Any condition listed in the WBQ0 Reject counter was true", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : HA", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.HA", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : HA : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : LLC OR SF Way", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.LLC_OR_SF_WAY", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : LLC OR SF Way : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : Way conflict with another request that caused the reject", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : LLC Victim", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.LLC_VICTIM", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : LLC Victim : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : PhyAddr Match", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.PA_MATCH", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : PhyAddr Match : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : Address match with an outstanding request that was rejected.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : SF Victim", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.SF_VICTIM", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : SF Victim : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry. : Requests did not generate Snoop filter victim", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "WBQ Rejects - Set 1 : Victim", + "EventCode": "0x29", + "EventName": "UNC_CHA_RxC_WBQ1_REJECT.VICTIM", + "PerPkg": "1", + "PublicDescription": "WBQ Rejects - Set 1 : Victim : Number of times a transaction flowing through the WBQ (Writeback Queue) had to retry.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : All", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.ALL", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : All : Counts the number of snoops issued by the HA.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : Broadcast snoop for Local Requests", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.BCST_LOCAL", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : Broadcast snoop for Local Requests : Counts the number of snoops issued by the HA. : Counts the number of broadcast snoops issued by the HA. This filter includes only requests coming from local sockets.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : Broadcast snoops for Remote Requests", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.BCST_REMOTE", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : Broadcast snoops for Remote Requests : Counts the number of snoops issued by the HA. : Counts the number of broadcast snoops issued by the HA.This filter includes only requests coming from remote sockets.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : Directed snoops for Local Requests", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.DIRECT_LOCAL", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : Directed snoops for Local Requests : Counts the number of snoops issued by the HA. : Counts the number of directed snoops issued by the HA. This filter includes only requests coming from local sockets.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : Directed snoops for Remote Requests", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.DIRECT_REMOTE", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : Directed snoops for Remote Requests : Counts the number of snoops issued by the HA. : Counts the number of directed snoops issued by the HA. This filter includes only requests coming from remote sockets.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : Broadcast or directed Snoops sent for Local Requests", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.LOCAL", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : Broadcast or directed Snoops sent for Local Requests : Counts the number of snoops issued by the HA. : Counts the number of broadcast or directed snoops issued by the HA per request. This filter includes only requests coming from the local socket.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoops Sent : Broadcast or directed Snoops sent for Remote Requests", + "EventCode": "0x51", + "EventName": "UNC_CHA_SNOOPS_SENT.REMOTE", + "PerPkg": "1", + "PublicDescription": "Snoops Sent : Broadcast or directed Snoops sent for Remote Requests : Counts the number of snoops issued by the HA. : Counts the number of broadcast or directed snoops issued by the HA per request. This filter includes only requests coming from the remote socket.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received : RSPCNFLCT*", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPCNFLCT", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received : RSPCNFLCT* : Counts the total number of RspI snoop responses received. Whenever a snoops are issued, one or more snoop responses will be returned depending on the topology of the system. In systems larger than 2s, when multiple snoops are returned this will count all the snoops that are received. For example, if 3 snoops were issued and returned RspI, RspS, and RspSFwd; then each of these sub-events would increment by 1. : Filters for snoops responses of RspConflict. This is returned when a snoop finds an existing outstanding transaction in a remote caching agent when it CAMs that caching agent. This triggers conflict resolution hardware. This covers both RspCnflct and RspCnflctWbI.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received : RspFwd", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPFWD", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received : RspFwd : Counts the total number of RspI snoop responses received. Whenever a snoops are issued, one or more snoop responses will be returned depending on the topology of the system. In systems larger than 2s, when multiple snoops are returned this will count all the snoops that are received. For example, if 3 snoops were issued and returned RspI, RspS, and RspSFwd; then each of these sub-events would increment by 1. : Filters for a snoop response of RspFwd to a CA request. This snoop response is only possible for RdCur when a snoop HITM/E in a remote caching agent and it directly forwards data to a requestor without changing the requestor's cache line state.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received : Rsp*Fwd*WB", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPFWDWB", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received : Rsp*Fwd*WB : Counts the total number of RspI snoop responses received. Whenever a snoops are issued, one or more snoop responses will be returned depending on the topology of the system. In systems larger than 2s, when multiple snoops are returned this will count all the snoops that are received. For example, if 3 snoops were issued and returned RspI, RspS, and RspSFwd; then each of these sub-events would increment by 1. : Filters for a snoop response of Rsp*Fwd*WB. This snoop response is only used in 4s systems. It is used when a snoop HITM's in a remote caching agent and it directly forwards data to a requestor, and simultaneously returns data to the home to be written back to memory.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "RspI Snoop Responses Received", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPI", + "PerPkg": "1", + "PublicDescription": "Counts when a transaction with the opcode type RspI Snoop Response was received which indicates the remote cache does not have the data, or when the remote cache silently evicts data (such as when an RFO: the Read for Ownership issued before a write hits non-modified data).", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "RspIFwd Snoop Responses Received", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPIFWD", + "PerPkg": "1", + "PublicDescription": "Counts when a a transaction with the opcode type RspIFwd Snoop Response was received which indicates a remote caching agent forwarded the data and the requesting agent is able to acquire the data in E (Exclusive) or M (modified) states. This is commonly returned with RFO (the Read for Ownership issued before a write) transactions. The snoop could have either been to a cacheline in the M,E,F (Modified, Exclusive or Forward) states.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "RspS Snoop Responses Received", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPS", + "PerPkg": "1", + "PublicDescription": "Counts when a transaction with the opcode type RspS Snoop Response was received which indicates when a remote cache has data but is not forwarding it. It is a way to let the requesting socket know that it cannot allocate the data in E state. No data is sent with S RspS.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "RspSFwd Snoop Responses Received", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPSFWD", + "PerPkg": "1", + "PublicDescription": "Counts when a a transaction with the opcode type RspSFwd Snoop Response was received which indicates a remote caching agent forwarded the data but held on to its current copy. This is common for data and code reads that hit in a remote socket in E (Exclusive) or F (Forward) state.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received : Rsp*WB", + "EventCode": "0x5c", + "EventName": "UNC_CHA_SNOOP_RESP.RSPWB", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received : Rsp*WB : Counts the total number of RspI snoop responses received. Whenever a snoops are issued, one or more snoop responses will be returned depending on the topology of the system. In systems larger than 2s, when multiple snoops are returned this will count all the snoops that are received. For example, if 3 snoops were issued and returned RspI, RspS, and RspSFwd; then each of these sub-events would increment by 1. : Filters for a snoop response of RspIWB or RspSWB. This is returned when a non-RFO request hits in M state. Data and Code Reads can return either RspIWB or RspSWB depending on how the system has been configured. InvItoE transactions will also return RspIWB because they must acquire ownership.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : RspCnflct", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPCNFLCT", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : RspCnflct : Number of snoop responses received for a Local request : Filters for snoops responses of RspConflict to local CA requests. This is returned when a snoop finds an existing outstanding transaction in a remote caching agent when it CAMs that caching agent. This triggers conflict resolution hardware. This covers both RspCnflct and RspCnflctWbI.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : RspFwd", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPFWD", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : RspFwd : Number of snoop responses received for a Local request : Filters for a snoop response of RspFwd to local CA requests. This snoop response is only possible for RdCur when a snoop HITM/E in a remote caching agent and it directly forwards data to a requestor without changing the requestor's cache line state.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : Rsp*FWD*WB", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPFWDWB", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : Rsp*FWD*WB : Number of snoop responses received for a Local request : Filters for a snoop response of Rsp*Fwd*WB to local CA requests. This snoop response is only used in 4s systems. It is used when a snoop HITM's in a remote caching agent and it directly forwards data to a requestor, and simultaneously returns data to the home to be written back to memory.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : RspI", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPI", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : RspI : Number of snoop responses received for a Local request : Filters for snoops responses of RspI to local CA requests. RspI is returned when the remote cache does not have the data, or when the remote cache silently evicts data (such as when an RFO hits non-modified data).", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : RspIFwd", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPIFWD", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : RspIFwd : Number of snoop responses received for a Local request : Filters for snoop responses of RspIFwd to local CA requests. This is returned when a remote caching agent forwards data and the requesting agent is able to acquire the data in E or M states. This is commonly returned with RFO transactions. It can be either a HitM or a HitFE.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : RspS", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPS", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : RspS : Number of snoop responses received for a Local request : Filters for snoop responses of RspS to local CA requests. RspS is returned when a remote cache has data but is not forwarding it. It is a way to let the requesting socket know that it cannot allocate the data in E state. No data is sent with S RspS.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : RspSFwd", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPSFWD", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : RspSFwd : Number of snoop responses received for a Local request : Filters for a snoop response of RspSFwd to local CA requests. This is returned when a remote caching agent forwards data but holds on to its current copy. This is common for data and code reads that hit in a remote socket in E or F state.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Snoop Responses Received Local : Rsp*WB", + "EventCode": "0x5d", + "EventName": "UNC_CHA_SNOOP_RESP_LOCAL.RSPWB", + "PerPkg": "1", + "PublicDescription": "Snoop Responses Received Local : Rsp*WB : Number of snoop responses received for a Local request : Filters for a snoop response of RspIWB or RspSWB to local CA requests. This is returned when a non-RFO request hits in M state. Data and Code Reads can return either RspIWB or RspSWB depending on how the system has been configured. InvItoE transactions will also return RspIWB because they must acquire ownership.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Misc Snoop Responses Received : MtoI RspIDataM", + "EventCode": "0x6b", + "EventName": "UNC_CHA_SNOOP_RSP_MISC.MTOI_RSPDATAM", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "Misc Snoop Responses Received : MtoI RspIFwdM", + "EventCode": "0x6b", + "EventName": "UNC_CHA_SNOOP_RSP_MISC.MTOI_RSPIFWDM", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "Misc Snoop Responses Received : Pull Data Partial - Hit LLC", + "EventCode": "0x6b", + "EventName": "UNC_CHA_SNOOP_RSP_MISC.PULLDATAPTL_HITLLC", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "Misc Snoop Responses Received : Pull Data Partial - Hit SF", + "EventCode": "0x6b", + "EventName": "UNC_CHA_SNOOP_RSP_MISC.PULLDATAPTL_HITSF", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "Misc Snoop Responses Received : RspIFwdPtl Hit LLC", + "EventCode": "0x6b", + "EventName": "UNC_CHA_SNOOP_RSP_MISC.RSPIFWDMPTL_HITLLC", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "Misc Snoop Responses Received : RspIFwdPtl Hit SF", + "EventCode": "0x6b", + "EventName": "UNC_CHA_SNOOP_RSP_MISC.RSPIFWDMPTL_HITSF", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : All", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.ALL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0xc001ffff", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DDR Access", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.DDR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DDR Access : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : SF/LLC Evictions", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.EVICT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : SF/LLC Evictions : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : TOR allocation occurred as a result of SF/LLC evictions (came from the ISMQ)", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just Hits", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.HIT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just Hits : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; All from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.; All locally initiated requests from IA Cores", + "UMask": "0xc001ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts;CLFlush from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.; CLFlush events that are initiated from the Core", + "UMask": "0xc8c7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts;CLFlushOpt from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CLFLUSHOPT", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.; CLFlushOpt events that are initiated from the Core", + "UMask": "0xc8d7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; CRd from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Code read from local IA that misses in the snoop filter", + "UMask": "0xc80fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; CRd Pref from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Code read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc88fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read from local IA that misses in the snoop filter", + "UMask": "0xc817ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd PTEs issued by iA Cores", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRDPTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd PTEs issued by iA Cores due to a page walk : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc837ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Opt from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read opt from local IA that misses in the snoop filter", + "UMask": "0xc827ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Opt Pref from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read opt prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8a7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Pref from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_DRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc897ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; Hits from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0xc001fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; CRd hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Code read from local IA that hits in the snoop filter", + "UMask": "0xc80ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; CRd Pref hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Code read prefetch from local IA that hits in the snoop filter", + "UMask": "0xc88ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "All requests issued from IA cores to CXL accelerator memory regions that hit the LLC.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018101", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_HIT_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c0008101", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRD", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read from local IA that hits in the snoop filter", + "UMask": "0xc817fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd PTEs issued by iA Cores that Hit the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRDPTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd PTEs issued by iA Cores due to page walks that hit the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc837fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Opt hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read opt from local IA that hits in the snoop filter", + "UMask": "0xc827fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Opt Pref hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read opt prefetch from local IA that hits in the snoop filter", + "UMask": "0xc8a7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Pref hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_DRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read prefetch from local IA that hits in the snoop filter", + "UMask": "0xc897fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : ItoMs issued by iA Cores that Hit LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc47fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefCode hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch code read from local IA that hits in the snoop filter", + "UMask": "0xcccffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefData hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch data read from local IA that hits in the snoop filter", + "UMask": "0xccd7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefRFO hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch read for ownership from local IA that hits in the snoop filter", + "UMask": "0xccc7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership from local IA that hits in the snoop filter", + "UMask": "0xc807fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO Pref hits from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_HIT_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership prefetch from local IA that hits in the snoop filter", + "UMask": "0xc887fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts;ItoM from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_ITOM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.; ItoM events that are initiated from the Core", + "UMask": "0xcc47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : ItoMCacheNears issued by iA Cores", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefCode from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch code read from local IA.", + "UMask": "0xcccfff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefData from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch data read from local IA.", + "UMask": "0xccd7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefRFO from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch read for ownership from local IA that misses in the snoop filter", + "UMask": "0xccc7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; misses from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All requests from iA Cores that Missed the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for CRd misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode CRd", + "UMask": "0xc80ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "CRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRDMORPH_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c80b8201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : CRd issued by iA Cores that Missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc80efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; CRd Pref misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Code read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc88ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc88efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc88f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : CRd issued by iA Cores that Missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CRD_REMOTE", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc80f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "All requests issued from IA cores to CXL accelerator memory regions that miss the LLC.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c0008201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRd misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd", + "UMask": "0xc817fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "DRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRDMORPH_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8138201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd PTEs issued by iA Cores that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRDPTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : DRd PTEs issued by iA Cores due to a page walk that missed the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc837fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "DRds issued from an IA core which miss the L3 and target memory in a CXL type 2 memory expander card.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8178201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8168201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_CXL_EXP_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_CXL_EXP_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20c8168201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRds issued by IA Cores targeting DDR Mem that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_DDR", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target DDR memory", + "UMask": "0xc8178601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRd misses from local IA targeting local memory", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_LOCAL", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target local memory", + "UMask": "0xc816fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRds issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_LOCAL_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8168601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRds issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_LOCAL_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8168a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Opt misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read opt from local IA that misses in the snoop filter", + "UMask": "0xc827fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8268201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; DRd Opt Pref misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Data read opt prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8a7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8a68201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRds issued by iA Cores targeting PMM Mem that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PMM", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target PMM memory", + "UMask": "0xc8178a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRd Pref misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRD_PREF", + "UMask": "0xc897fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "L2 data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8978201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8968201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8978601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRd Pref misses from local IA targeting local memory", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRD_PREF, and target local memory", + "UMask": "0xc896fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_LOCAL_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8968601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_LOCAL_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8968a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8978a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRd Pref misses from local IA targeting remote memory", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRD_PREF, and target remote memory", + "UMask": "0xc8977e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_REMOTE_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8970601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_PREF_REMOTE_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8970a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for DRd misses from local IA targeting remote memory", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_REMOTE", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and target remote memory", + "UMask": "0xc8177e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRds issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_REMOTE_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8170601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : DRds issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_DRD_REMOTE_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8170a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : ItoMs issued by iA Cores that Missed LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc47fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefCode misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch code read from local IA that misses in the snoop filter", + "UMask": "0xcccffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "LLC Prefetch Code transactions issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFCODE_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10cccf8201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefData misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch data read from local IA that misses in the snoop filter", + "UMask": "0xccd7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "LLC data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccd78201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10ccd68201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; LLCPrefRFO misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Last level cache prefetch read for ownership from local IA that misses in the snoop filter", + "UMask": "0xccc7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "L2 RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFRFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8878201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFRFO_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFRFO_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8868201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8668601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCILF_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8668a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86e8601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_LOCAL_WCIL_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86e8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8670601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCILF_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8670a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f0601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_REMOTE_WCIL_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f0a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc807fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "RFO and L2 RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFOMORPH_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8038201", + "Unit": "CHA" + }, + { + "BriefDescription": "RFOs issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8078201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8068201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_CXL_EXP_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_CXL_EXP_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20c8068201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts RFO misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc806fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO pref misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc887fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "LLC RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccc78201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_CXL_ACC_LOCAL", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10ccc68201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO prefetch misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc886fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO prefetch misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8877e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO misses from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_RFO_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Inserts Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc8077e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : UCRdFs issued by iA Cores that Missed LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_UCRDF", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc877de01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLF issued by iA Cores that Missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc867fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting DDR that missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8678601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLFs issued by iA Cores targeting PMM that missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCILF_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8678a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores targeting DDR that missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f8601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores targeting PMM that missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WCIL_PMM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WiLs issued by iA Cores that Missed LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_MISS_WIL", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc87fde01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc807ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO pref from local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc887ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts;SpecItoM from Local IA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_SPECITOM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.; SpecItoM events that are initiated from the Core", + "UMask": "0xcc57ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WBEFtoEs issued by an IA Core. Non Modified Write Backs", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBEFTOE", + "PerPkg": "1", + "PublicDescription": "WbEFtoEs issued by iA Cores . (Non Modified Write Backs) :Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc3fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WBEFtoEs issued by an IA Core. Non Modified Write Backs", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBEFTOI", + "PerPkg": "1", + "PublicDescription": "WbEFtoEs issued by iA Cores . (Non Modified Write Backs) :Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc37ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WBEFtoEs issued by an IA Core. Non Modified Write Backs", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBMTOE", + "PerPkg": "1", + "PublicDescription": "WbEFtoEs issued by iA Cores . (Non Modified Write Backs) :Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc2fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WbMtoIs issued by an iA Cores. Modified Write Backs", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBMTOI", + "PerPkg": "1", + "PublicDescription": "WbMtoIs issued by iA Cores . (Modified Write Backs) :Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc27ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WBEFtoEs issued by an IA Core. Non Modified Write Backs", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WBSTOI", + "PerPkg": "1", + "PublicDescription": "WbEFtoEs issued by iA Cores . (Non Modified Write Backs) :Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc67ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLs issued by iA Cores", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WCIL", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WCiLF issued by iA Cores", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IA_WCILF", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc867ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; All from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : CLFlushes issued by IO Devices", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8c3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; Hits from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; ItoM hits from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RdCur and FsRdCur hits from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices that hit the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8f3fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO hits from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc803fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for ItoM from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOM", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IO with the opcode ItoM", + "UMask": "0xcc43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for ItoMCacheNears from IO devices.", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IO devices with the opcode ItoMCacheNears. This event indicates a partial write request.", + "UMask": "0xcd43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; Misses from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; ItoM misses from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RdCur and FsRdCur misses from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PCIRdCurs issued by IO Devices that missed the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8f3fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO misses from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by IO Devices that missed the LLC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc803fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts for RdCur from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "Inserts into the TOR from local IO with the opcode RdCur", + "UMask": "0xc8f3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; RFO from local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RFOs issued by IO Devices : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc803ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WbMtoIs issued by IO Devices", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IO_WBMTOI", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc23ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : IPQ", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IPQ", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : IPQ : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : IRQ - iA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IRQ_IA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : IRQ - iA : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : From an iA Core", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : IRQ - Non iA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.IRQ_NON_IA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : IRQ - Non iA : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just ISOC", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.ISOC", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just ISOC : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just Local Targets", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOCAL_TGT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just Local Targets : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : All from Local iA and IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOC_ALL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Local iA and IO : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : All locally initiated requests", + "UMask": "0xc000ff05", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : All from Local iA", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOC_IA", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Local iA : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : All locally initiated requests from iA Cores", + "UMask": "0xc000ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : All from Local IO", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.LOC_IO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Local IO : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : All locally generated IO traffic", + "UMask": "0xc000ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Match the Opcode in b[29:19] of the extended umask field", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.MATCH_OPC", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Match the Opcode in b[29:19] of the extended umask field : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just Misses", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.MISS", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just Misses : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : MMCFG Access", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.MMCFG", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : MMCFG Access : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : MMIO Access", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.MMIO", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : MMIO Access : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just NearMem", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.NEARMEM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just NearMem : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just NonCoherent", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.NONCOH", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just NonCoherent : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just NotNearMem", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.NOT_NEARMEM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just NotNearMem : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : PMM Access", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.PMM", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PM Access : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Match the PreMorphed Opcode in b[29:19] of the extended umask field", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.PREMORPH_OPC", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Match the PreMorphed Opcode in b[29:19] of the extended umask field : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : PRQ - IOSF", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.PRQ_IOSF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PRQ - IOSF : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : From a PCIe Device", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : PRQ - Non IOSF", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.PRQ_NON_IOSF", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : PRQ - Non IOSF : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : Just Remote Targets", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.REMOTE_TGT", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : Just Remote Targets : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : All from Remote", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.REM_ALL", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All from Remote : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : All remote requests (e.g. snoops, writebacks) that came from remote sockets", + "UMask": "0xc001ffc8", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : All Snoops from Remote", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.REM_SNPS", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : All Snoops from Remote : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. : All snoops to this LLC that came from remote sockets", + "UMask": "0xc001ff08", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : RRQ", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.RRQ", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : RRQ : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts; All Snoops from Remote", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.SNPS_FROM_REM", + "PerPkg": "1", + "PublicDescription": "Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent. All snoops to this LLC that came from remote sockets.", + "UMask": "0xc001ff08", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Inserts : WBQ", + "EventCode": "0x35", + "EventName": "UNC_CHA_TOR_INSERTS.WBQ", + "PerPkg": "1", + "PublicDescription": "TOR Inserts : WBQ : Counts the number of entries successfully inserted into the TOR that match qualifications specified by the subevent.", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : All", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.ALL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "UMask": "0xc001ffff", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DDR Access", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DDR Access : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : SF/LLC Evictions", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.EVICT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : SF/LLC Evictions : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : TOR allocation occurred as a result of SF/LLC evictions (came from the ISMQ)", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just Hits", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.HIT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just Hits : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; All from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CLFlushes issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CLFlushes issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8c7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CLFlushOpts issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CLFLUSHOPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CLFlushOpts issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8d7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; CRd from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read from local IA that misses in the snoop filter", + "UMask": "0xc80fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; CRd Pref from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc88fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read from local IA that misses in the snoop filter", + "UMask": "0xc817ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRdPte issued by iA Cores due to a page walk", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRDPTE", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "TOR Occupancy : DRdPte issued by iA Cores due to a page walk : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc837ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Opt from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read opt from local IA that misses in the snoop filter", + "UMask": "0xc827ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Opt Pref from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read opt prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8a7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Pref from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_DRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc897ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; Hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from iA Cores that Hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; CRd hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read from local IA that hits in the snoop filter", + "UMask": "0xc80ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; CRd Pref hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read prefetch from local IA that hits in the snoop filter", + "UMask": "0xc88ffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All requests issued from IA cores to CXL accelerator memory regions that hit the LLC.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018101", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c0008101", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read from local IA that hits in the snoop filter", + "UMask": "0xc817fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRdPte issued by iA Cores due to a page walk that hit the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRDPTE", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "TOR Occupancy : DRdPte issued by iA Cores due to a page walk that hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc837fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Opt hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read opt from local IA that hits in the snoop filter", + "UMask": "0xc827fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Opt Pref hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read opt prefetch from local IA that hits in the snoop filter", + "UMask": "0xc8a7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Pref hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_DRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read prefetch from local IA that hits in the snoop filter", + "UMask": "0xc897fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMs issued by iA Cores that Hit LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by iA Cores that Hit LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc47fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefCode hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch code read from local IA that hits in the snoop filter", + "UMask": "0xcccffd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefData hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch data read from local IA that hits in the snoop filter", + "UMask": "0xccd7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefRFO hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch read for ownership from local IA that hits in the snoop filter", + "UMask": "0xccc7fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership from local IA that hits in the snoop filter", + "UMask": "0xc807fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO Pref hits from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership prefetch from local IA that hits in the snoop filter", + "UMask": "0xc887fd01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMs issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMCacheNears issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd47ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefCode from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch data read from local IA.", + "UMask": "0xcccfff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefData from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch data read from local IA that misses in the snoop filter", + "UMask": "0xccd7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefRFO from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch read for ownership from local IA that misses in the snoop filter", + "UMask": "0xccc7ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; Misses from Local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from iA Cores that Missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; CRd misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read from local IA that misses in the snoop filter", + "UMask": "0xc80ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for CRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRDMORPH_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c80b8201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CRd issued by iA Cores that Missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd issued by iA Cores that Missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc80efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; CRd Pref misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Code read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc88ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc88efe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd_Prefs issued by iA Cores that Missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc88f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CRd issued by iA Cores that Missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CRD_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CRd issued by iA Cores that Missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc80f7e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for All requests issued from IA cores to CXL accelerator memory regions that miss the LLC.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c0018201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c0008201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRd misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD", + "PerPkg": "1", + "PublicDescription": "Number of cycles for elements in the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd", + "UMask": "0xc817fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRDMORPH_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8138201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRdPte issued by iA Cores due to a page walk that missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRDPTE", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "TOR Occupancy : DRdPte issued by iA Cores due to a page walk that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc837fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRds and equivalent opcodes issued from an IA core which miss the L3 and target memory in a CXL type 2 memory expander card.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8178201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8168201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_EXP_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_EXP_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20c8168201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRds issued by iA Cores targeting DDR Mem that Missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_DDR", + "PerPkg": "1", + "PublicDescription": "Number of cycles for elements in the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target DDR memory", + "UMask": "0xc8178601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRd misses from local IA targeting local memory", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_LOCAL", + "PerPkg": "1", + "PublicDescription": "Number of cycles for elements in the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target local memory", + "UMask": "0xc816fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRds issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_LOCAL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRds issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8168601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRds issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_LOCAL_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRds issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8168a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Opt misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read opt from local IA that misses in the snoop filter", + "UMask": "0xc827fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8268201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Opt Pref misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read opt prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8a7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_PREF_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_PREF_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8a68201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRds issued by iA Cores targeting PMM Mem that Missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PMM", + "PerPkg": "1", + "PublicDescription": "Number of cycles for elements in the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target PMM memory", + "UMask": "0xc8178a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Pref misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc897fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for L2 data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8978201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8968201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8978601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Pref misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc896fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_LOCAL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8968601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_LOCAL_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8968a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8978a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; DRd Pref misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Data read prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8977e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_REMOTE_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8970601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_REMOTE_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRd_Prefs issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8970a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for DRd misses from local IA targeting remote memory", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_REMOTE", + "PerPkg": "1", + "PublicDescription": "Number of cycles for elements in the TOR from local IA cores which miss the LLC and snoop filter with the opcode DRd, and which target remote memory", + "UMask": "0xc8177e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRds issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_REMOTE_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRds issued by iA Cores targeting DDR Mem that Missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8170601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : DRds issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_REMOTE_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : DRds issued by iA Cores targeting PMM Mem that Missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8170a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMs issued by iA Cores that Missed LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by iA Cores that Missed LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc47fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefCode misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFCODE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch code read from local IA that misses in the snoop filter", + "UMask": "0xcccffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for LLC Prefetch Code transactions issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFCODE_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10cccf8201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefData misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch data read from local IA that misses in the snoop filter", + "UMask": "0xccd7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for LLC data prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccd78201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10ccd68201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; LLCPrefRFO misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Last level cache prefetch read for ownership from local IA that misses in the snoop filter", + "UMask": "0xccc7fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for L2 RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8878201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8868201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8668601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCILF_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8668a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86e8601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed locally", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LOCAL_WCIL_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed locally : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86e8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8670601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCILF_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8670a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f0601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_REMOTE_WCIL_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC - HOMed remotely : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f0a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc807fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for RFO and L2 RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFOMORPH_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8038201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for RFOs issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10c8078201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10c8068201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_EXP_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_EXP_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x20c8068201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc806fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO prefetch misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc887fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy for LLC RFO prefetches issued from an IA core which miss the L3 and target memory in a CXL type 2 accelerator.", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_CXL_ACC", + "PerPkg": "1", + "UMask": "0x10ccc78201", + "Unit": "CHA" + }, + { + "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_CXL_ACC_LOCAL", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_CXL_ACC_LOCAL", + "PerPkg": "1", + "PortMask": "0x000", + "UMask": "0x10ccc68201", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO prefetch misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_LOCAL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc886fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO prefetch misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc8877e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO misses from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_REMOTE", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc8077e01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : UCRdFs issued by iA Cores that Missed LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_UCRDF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : UCRdFs issued by iA Cores that Missed LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc877de01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores that Missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCIL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores that Missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86ffe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLF issued by iA Cores that Missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCILF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLF issued by iA Cores that Missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc867fe01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCILF_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting DDR that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8678601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCILF_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLFs issued by iA Cores targeting PMM that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8678a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCIL_DDR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting DDR that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f8601", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WCIL_PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores targeting PMM that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86f8a01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WiLs issued by iA Cores that Missed LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_WIL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WiLs issued by iA Cores that Missed LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc87fde01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership from local IA that misses in the snoop filter", + "UMask": "0xc807ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO prefetch from local IA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_RFO_PREF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy; Read for ownership prefetch from local IA that misses in the snoop filter", + "UMask": "0xc887ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : SpecItoMs issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_SPECITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : SpecItoMs issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc57ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WbMtoIs issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_WBMTOI", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WbMtoIs issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc27ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLs issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_WCIL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLs issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc86fff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WCiLF issued by iA Cores", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_WCILF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WCiLF issued by iA Cores : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc867ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; All from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : CLFlushes issued by IO Devices", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_CLFLUSH", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : CLFlushes issued by IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8c3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; Hits from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from IO Devices that hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; ITOM hits from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices that Hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd43fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RdCur and FsRdCur hits from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices that hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8f3fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO hits from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_HIT_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by IO Devices that hit the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc803fd04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; ITOM from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_ITOMCACHENEAR", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd43ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; Misses from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All requests from IO Devices that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc001fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; ITOM misses from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMs issued by IO Devices that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_ITOMCACHENEAR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : ItoMCacheNears, indicating a partial write request, from IO Devices that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcd43fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RdCur and FsRdCur misses from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8f3fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RFO misses from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_MISS_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by IO Devices that missed the LLC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc803fe04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; RdCur and FsRdCur from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_PCIRDCUR", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PCIRdCurs issued by IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc8f3ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; ItoM from local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_RFO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RFOs issued by IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xc803ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WbMtoIs issued by IO Devices", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IO_WBMTOI", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WbMtoIs issued by IO Devices : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. Does not include addressless requests such as locks and interrupts.", + "UMask": "0xcc23ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : IPQ", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IPQ", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : IPQ : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : IRQ - iA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IRQ_IA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : IRQ - iA : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : From an iA Core", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : IRQ - Non iA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.IRQ_NON_IA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : IRQ - Non iA : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just ISOC", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.ISOC", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just ISOC : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just Local Targets", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOCAL_TGT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just Local Targets : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : All from Local iA and IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOC_ALL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Local iA and IO : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : All locally initiated requests", + "UMask": "0xc000ff05", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : All from Local iA", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOC_IA", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Local iA : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : All locally initiated requests from iA Cores", + "UMask": "0xc000ff01", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : All from Local IO", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.LOC_IO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Local IO : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : All locally generated IO traffic", + "UMask": "0xc000ff04", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Match the Opcode in b[29:19] of the extended umask field", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.MATCH_OPC", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Match the Opcode in b[29:19] of the extended umask field : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just Misses", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.MISS", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just Misses : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : MMCFG Access", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.MMCFG", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : MMCFG Access : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : MMIO Access", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.MMIO", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : MMIO Access : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just NearMem", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.NEARMEM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just NearMem : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just NonCoherent", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.NONCOH", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just NonCoherent : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just NotNearMem", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.NOT_NEARMEM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just NotNearMem : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : PMM Access", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.PMM", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PMM Access : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent.", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Match the PreMorphed Opcode in b[29:19] of the extended umask field", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.PREMORPH_OPC", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Match the PreMorphed Opcode in b[29:19] of the extended umask field : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : PRQ - IOSF", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.PRQ", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PRQ - IOSF : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : From a PCIe Device", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : PRQ - Non IOSF", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.PRQ_NON_IOSF", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : PRQ - Non IOSF : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : Just Remote Targets", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.REMOTE_TGT", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : Just Remote Targets : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : All from Remote", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.REM_ALL", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All from Remote : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : All remote requests (e.g. snoops, writebacks) that came from remote sockets", + "UMask": "0xc001ffc8", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : All Snoops from Remote", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.REM_SNPS", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : All Snoops from Remote : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T : All snoops to this LLC that came from remote sockets", + "UMask": "0xc001ff08", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : RRQ", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.RRQ", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : RRQ : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy; All Snoops from Remote", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.SNPS_FROM_REM", + "PerPkg": "1", + "PublicDescription": "For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. All snoops to this LLC that came from remote sockets.", + "UMask": "0xc001ff08", + "Unit": "CHA" + }, + { + "BriefDescription": "TOR Occupancy : WBQ", + "EventCode": "0x36", + "EventName": "UNC_CHA_TOR_OCCUPANCY.WBQ", + "PerPkg": "1", + "PublicDescription": "TOR Occupancy : WBQ : For each cycle, this event accumulates the number of valid entries in the TOR that match qualifications specified by the subevent. T", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "WbPushMtoI : Pushed to LLC", + "EventCode": "0x56", + "EventName": "UNC_CHA_WB_PUSH_MTOI.LLC", + "PerPkg": "1", + "PublicDescription": "WbPushMtoI : Pushed to LLC : Counts the number of times when the CHA was received WbPushMtoI : Counts the number of times when the CHA was able to push WbPushMToI to LLC", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "WbPushMtoI : Pushed to Memory", + "EventCode": "0x56", + "EventName": "UNC_CHA_WB_PUSH_MTOI.MEM", + "PerPkg": "1", + "PublicDescription": "WbPushMtoI : Pushed to Memory : Counts the number of times when the CHA was received WbPushMtoI : Counts the number of times when the CHA was unable to push WbPushMToI to LLC (hence pushed it to MEM)", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx WRITE Credits Empty : MC0", + "EventCode": "0x5a", + "EventName": "UNC_CHA_WRITE_NO_CREDITS.MC0", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx WRITE Credits Empty : MC0 : Counts the number of times when there are no credits available for sending WRITEs from the CHA into the iMC. In order to send WRITEs into the memory controller, the HA must first acquire a credit for the iMC's BL Ingress queue. : Filter for memory controller 0 only.", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx WRITE Credits Empty : MC1", + "EventCode": "0x5a", + "EventName": "UNC_CHA_WRITE_NO_CREDITS.MC1", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx WRITE Credits Empty : MC1 : Counts the number of times when there are no credits available for sending WRITEs from the CHA into the iMC. In order to send WRITEs into the memory controller, the HA must first acquire a credit for the iMC's BL Ingress queue. : Filter for memory controller 1 only.", + "UMask": "0x2", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx WRITE Credits Empty : MC2", + "EventCode": "0x5a", + "EventName": "UNC_CHA_WRITE_NO_CREDITS.MC2", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx WRITE Credits Empty : MC2 : Counts the number of times when there are no credits available for sending WRITEs from the CHA into the iMC. In order to send WRITEs into the memory controller, the HA must first acquire a credit for the iMC's BL Ingress queue. : Filter for memory controller 2 only.", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx WRITE Credits Empty : MC3", + "EventCode": "0x5a", + "EventName": "UNC_CHA_WRITE_NO_CREDITS.MC3", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx WRITE Credits Empty : MC3 : Counts the number of times when there are no credits available for sending WRITEs from the CHA into the iMC. In order to send WRITEs into the memory controller, the HA must first acquire a credit for the iMC's BL Ingress queue. : Filter for memory controller 3 only.", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx WRITE Credits Empty : MC4", + "EventCode": "0x5a", + "EventName": "UNC_CHA_WRITE_NO_CREDITS.MC4", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx WRITE Credits Empty : MC4 : Counts the number of times when there are no credits available for sending WRITEs from the CHA into the iMC. In order to send WRITEs into the memory controller, the HA must first acquire a credit for the iMC's BL Ingress queue. : Filter for memory controller 4 only.", + "UMask": "0x10", + "Unit": "CHA" + }, + { + "BriefDescription": "CHA iMC CHNx WRITE Credits Empty : MC5", + "EventCode": "0x5a", + "EventName": "UNC_CHA_WRITE_NO_CREDITS.MC5", + "PerPkg": "1", + "PublicDescription": "CHA iMC CHNx WRITE Credits Empty : MC5 : Counts the number of times when there are no credits available for sending WRITEs from the CHA into the iMC. In order to send WRITEs into the memory controller, the HA must first acquire a credit for the iMC's BL Ingress queue. : Filter for memory controller 5 only.", + "UMask": "0x20", + "Unit": "CHA" + }, + { + "BriefDescription": "XPT Prefetches : Dropped (on 0?) - Conflict", + "EventCode": "0x6f", + "EventName": "UNC_CHA_XPT_PREF.DROP0_CONFLICT", + "PerPkg": "1", + "PublicDescription": "XPT Prefetches : Dropped (on 0?) - Conflict : Number of XPT prefetches dropped due to AD CMS write port contention", + "UMask": "0x8", + "Unit": "CHA" + }, + { + "BriefDescription": "XPT Prefetches : Dropped (on 0?) - No Credits", + "EventCode": "0x6f", + "EventName": "UNC_CHA_XPT_PREF.DROP0_NOCRD", + "PerPkg": "1", + "PublicDescription": "XPT Prefetches : Dropped (on 0?) - No Credits : Number of XPT prefetches dropped due to lack of XPT AD egress credits", + "UMask": "0x4", + "Unit": "CHA" + }, + { + "BriefDescription": "XPT Prefetches : Dropped (on 1?) - Conflict", + "EventCode": "0x6f", + "EventName": "UNC_CHA_XPT_PREF.DROP1_CONFLICT", + "PerPkg": "1", + "PublicDescription": "XPT Prefetches : Dropped (on 1?) - Conflict : Number of XPT prefetches dropped due to AD CMS write port contention", + "UMask": "0x80", + "Unit": "CHA" + }, + { + "BriefDescription": "XPT Prefetches : Dropped (on 1?) - No Credits", + "EventCode": "0x6f", + "EventName": "UNC_CHA_XPT_PREF.DROP1_NOCRD", + "PerPkg": "1", + "PublicDescription": "XPT Prefetches : Dropped (on 1?) - No Credits : Number of XPT prefetches dropped due to lack of XPT AD egress credits", + "UMask": "0x40", + "Unit": "CHA" + }, + { + "BriefDescription": "XPT Prefetches : Sent (on 0?)", + "EventCode": "0x6f", + "EventName": "UNC_CHA_XPT_PREF.SENT0", + "PerPkg": "1", + "PublicDescription": "XPT Prefetches : Sent (on 0?) : Number of XPT prefetches sent", + "UMask": "0x1", + "Unit": "CHA" + }, + { + "BriefDescription": "XPT Prefetches : Sent (on 1?)", + "EventCode": "0x6f", + "EventName": "UNC_CHA_XPT_PREF.SENT1", + "PerPkg": "1", + "PublicDescription": "XPT Prefetches : Sent (on 1?) : Number of XPT prefetches sent", + "UMask": "0x10", + "Unit": "CHA" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cxl.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cxl.json new file mode 100644 index 000000000000..f3e84fd88de3 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-cxl.json @@ -0,0 +1,450 @@ +[ + { + "BriefDescription": "Counts the number of lfclk ticks", + "EventCode": "0x01", + "EventName": "UNC_CXLCM_CLOCKTICKS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Mem Rxx AGF 0", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.CACHE_DATA", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Req AGF0", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.CACHE_REQ0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Rsp AGF", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.CACHE_REQ1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Data AGF", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.CACHE_RSP0", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Rsp AGF", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.CACHE_RSP1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Req AGF 1", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.MEM_DATA", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Mem Data AGF", + "EventCode": "0x43", + "EventName": "UNC_CXLCM_RxC_AGF_INSERTS.MEM_REQ", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Flits with AK set", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.AK_HDR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Flits with BE set", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.BE_HDR", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of control flits received", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.CTRL", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Headerless flits received", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.NO_HDR", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of protocol flits received", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.PROT", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Flits with SZ set", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.SZ_HDR", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of flits received", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.VALID", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of valid messages in the flit", + "EventCode": "0x4b", + "EventName": "UNC_CXLCM_RxC_FLITS.VALID_MSG", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of CRC errors detected", + "EventCode": "0x40", + "EventName": "UNC_CXLCM_RxC_MISC.CRC_ERRORS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Init flits sent", + "EventCode": "0x40", + "EventName": "UNC_CXLCM_RxC_MISC.INIT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of LLCRD flits sent", + "EventCode": "0x40", + "EventName": "UNC_CXLCM_RxC_MISC.LLCRD", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Retry flits sent", + "EventCode": "0x40", + "EventName": "UNC_CXLCM_RxC_MISC.RETRY", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles the Packing Buffer is Full", + "EventCode": "0x52", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_FULL.CACHE_DATA", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles the Packing Buffer is Full", + "EventCode": "0x52", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_FULL.CACHE_REQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles the Packing Buffer is Full", + "EventCode": "0x52", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_FULL.CACHE_RSP", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles the Packing Buffer is Full", + "EventCode": "0x52", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_FULL.MEM_DATA", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles the Packing Buffer is Full", + "EventCode": "0x52", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_FULL.MEM_REQ", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Data Packing buffer", + "EventCode": "0x41", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_INSERTS.CACHE_DATA", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Req Packing buffer", + "EventCode": "0x41", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_INSERTS.CACHE_REQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Rsp Packing buffer", + "EventCode": "0x41", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_INSERTS.CACHE_RSP", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Mem Data Packing buffer", + "EventCode": "0x41", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_INSERTS.MEM_DATA", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Mem Rxx Packing buffer", + "EventCode": "0x41", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_INSERTS.MEM_REQ", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles of Not Empty for Cache Data Packing buffer", + "EventCode": "0x42", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_NE.CACHE_DATA", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles of Not Empty for Cache Req Packing buffer", + "EventCode": "0x42", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_NE.CACHE_REQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles of Not Empty for Cache Rsp Packing buffer", + "EventCode": "0x42", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_NE.CACHE_RSP", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles of Not Empty for Mem Data Packing buffer", + "EventCode": "0x42", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_NE.MEM_DATA", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of cycles of Not Empty for Mem Rxx Packing buffer", + "EventCode": "0x42", + "EventName": "UNC_CXLCM_RxC_PACK_BUF_NE.MEM_REQ", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Flits with AK set", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.AK_HDR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Flits with BE set", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.BE_HDR", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of control flits packed", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.CTRL", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Headerless flits packed", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.NO_HDR", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of protocol flits packed", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.PROT", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of Flits with SZ set", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.SZ_HDR", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Count the number of flits packed", + "EventCode": "0x05", + "EventName": "UNC_CXLCM_TxC_FLITS.VALID", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Data Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.CACHE_DATA", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Req Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.CACHE_REQ0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Rsp1 Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.CACHE_REQ1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Rsp0 Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.CACHE_RSP0", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Cache Req Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.CACHE_RSP1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Mem Data Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.MEM_DATA", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Number of Allocation to Mem Rxx Packing buffer", + "EventCode": "0x02", + "EventName": "UNC_CXLCM_TxC_PACK_BUF_INSERTS.MEM_REQ", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLCM" + }, + { + "BriefDescription": "Counts the number of uclk ticks", + "EventCode": "0x01", + "EventName": "UNC_CXLDP_CLOCKTICKS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLDP" + }, + { + "BriefDescription": "Number of Allocation to M2S Data AGF", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.M2S_DATA", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "CXLDP" + }, + { + "BriefDescription": "Number of Allocation to M2S Req AGF", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.M2S_REQ", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "CXLDP" + }, + { + "BriefDescription": "Number of Allocation to U2C Data AGF", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.U2C_DATA", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "CXLDP" + }, + { + "BriefDescription": "Number of Allocation to U2C Req AGF", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.U2C_REQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "CXLDP" + }, + { + "BriefDescription": "Number of Allocation to U2C Rsp AGF 0", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.U2C_RSP0", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "CXLDP" + }, + { + "BriefDescription": "Number of Allocation to U2C Rsp AGF 1", + "EventCode": "0x02", + "EventName": "UNC_CXLDP_TxC_AGF_INSERTS.U2C_RSP1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "CXLDP" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-interconnect.json new file mode 100644 index 000000000000..09d840c7da4c --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-interconnect.json @@ -0,0 +1,6199 @@ +[ + { + "BriefDescription": "Total IRP occupancy of inbound read and write requests to coherent memory.", + "EventCode": "0x0f", + "EventName": "UNC_I_CACHE_TOTAL_OCCUPANCY.MEM", + "PerPkg": "1", + "PublicDescription": "Total IRP occupancy of inbound read and write requests to coherent memory. This is effectively the sum of read occupancy and write occupancy.", + "UMask": "0x4", + "Unit": "IRP" + }, + { + "BriefDescription": "IRP Clockticks", + "EventCode": "0x01", + "EventName": "UNC_I_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of IRP clock cycles while the event is enabled", + "Unit": "IRP" + }, + { + "BriefDescription": "FAF RF full", + "EventCode": "0x17", + "EventName": "UNC_I_FAF_FULL", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "FAF - request insert from TC.", + "EventCode": "0x18", + "EventName": "UNC_I_FAF_INSERTS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "FAF occupancy", + "EventCode": "0x19", + "EventName": "UNC_I_FAF_OCCUPANCY", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "FAF allocation -- sent to ADQ", + "EventCode": "0x16", + "EventName": "UNC_I_FAF_TRANSACTIONS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": ": All Inserts Outbound (BL, AK, Snoops)", + "EventCode": "0x20", + "EventName": "UNC_I_IRP_ALL.EVICTS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "IRP" + }, + { + "BriefDescription": ": All Inserts Inbound (p2p + faf + cset)", + "EventCode": "0x20", + "EventName": "UNC_I_IRP_ALL.INBOUND_INSERTS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "IRP" + }, + { + "BriefDescription": ": All Inserts Outbound (BL, AK, Snoops)", + "EventCode": "0x20", + "EventName": "UNC_I_IRP_ALL.OUTBOUND_INSERTS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Cache Inserts of Atomic Transactions as Secondary", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.2ND_ATOMIC_INSERT", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Cache Inserts of Read Transactions as Secondary", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.2ND_RD_INSERT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Cache Inserts of Write Transactions as Secondary", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.2ND_WR_INSERT", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Fastpath Rejects", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.FAST_REJ", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Fastpath Requests", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.FAST_REQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Fastpath Transfers From Primary to Secondary", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.FAST_XFER", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Prefetch Ack Hints From Primary to Secondary", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.PF_ACK_HINT", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "IRP" + }, + { + "BriefDescription": "Counts Timeouts - Set 0 : Slow path fwpf didn't find prefetch", + "EventCode": "0x1e", + "EventName": "UNC_I_MISC0.SLOWPATH_FWPF_NO_PRF", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Lost Forward", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.LOST_FWD", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Lost Forward : Snoop pulled away ownership before a write was committed", + "UMask": "0x10", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Received Invalid", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.SEC_RCVD_INVLD", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Received Invalid : Secondary received a transfer that did not have sufficient MESI state", + "UMask": "0x20", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Received Valid", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.SEC_RCVD_VLD", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Received Valid : Secondary received a transfer that did have sufficient MESI state", + "UMask": "0x40", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Slow Transfer of E Line", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.SLOW_E", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Slow Transfer of E Line : Secondary received a transfer that did have sufficient MESI state", + "UMask": "0x4", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Slow Transfer of I Line", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.SLOW_I", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Slow Transfer of I Line : Snoop took cacheline ownership before write from data was committed.", + "UMask": "0x1", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Slow Transfer of M Line", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.SLOW_M", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Slow Transfer of M Line : Snoop took cacheline ownership before write from data was committed.", + "UMask": "0x8", + "Unit": "IRP" + }, + { + "BriefDescription": "Misc Events - Set 1 : Slow Transfer of S Line", + "EventCode": "0x1f", + "EventName": "UNC_I_MISC1.SLOW_S", + "PerPkg": "1", + "PublicDescription": "Misc Events - Set 1 : Slow Transfer of S Line : Secondary received a transfer that did not have sufficient MESI state", + "UMask": "0x2", + "Unit": "IRP" + }, + { + "BriefDescription": "Responses to snoops of any type that hit M, E, S or I line in the IIO", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT", + "PerPkg": "1", + "PublicDescription": "Responses to snoops of any type (code, data, invalidate) that hit M, E, S or I line in the IIO", + "UMask": "0x7e", + "Unit": "IRP" + }, + { + "BriefDescription": "Responses to snoops of any type that hit E or S line in the IIO cache", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT_ES", + "PerPkg": "1", + "PublicDescription": "Responses to snoops of any type (code, data, invalidate) that hit E or S line in the IIO cache", + "UMask": "0x74", + "Unit": "IRP" + }, + { + "BriefDescription": "Responses to snoops of any type that hit I line in the IIO cache", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT_I", + "PerPkg": "1", + "PublicDescription": "Responses to snoops of any type (code, data, invalidate) that hit I line in the IIO cache", + "UMask": "0x72", + "Unit": "IRP" + }, + { + "BriefDescription": "Responses to snoops of any type that hit M line in the IIO cache", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_HIT_M", + "PerPkg": "1", + "PublicDescription": "Responses to snoops of any type (code, data, invalidate) that hit M line in the IIO cache", + "UMask": "0x78", + "Unit": "IRP" + }, + { + "BriefDescription": "Responses to snoops of any type that miss the IIO cache", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.ALL_MISS", + "PerPkg": "1", + "PublicDescription": "Responses to snoops of any type (code, data, invalidate) that miss the IIO cache", + "UMask": "0x71", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : Hit E or S", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.HIT_ES", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : Hit I", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.HIT_I", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : Hit M", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.HIT_M", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : Miss", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.MISS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : SnpCode", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.SNPCODE", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : SnpData", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.SNPDATA", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "IRP" + }, + { + "BriefDescription": "Snoop Responses : SnpInv", + "EventCode": "0x12", + "EventName": "UNC_I_SNOOP_RESP.SNPINV", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "IRP" + }, + { + "BriefDescription": "Inbound write (fast path) requests received by the IRP.", + "EventCode": "0x11", + "EventName": "UNC_I_TRANSACTIONS.WR_PREF", + "PerPkg": "1", + "PublicDescription": "Inbound write (fast path) requests to coherent memory, received by the IRP resulting in write ownership requests issued by IRP to the mesh.", + "UMask": "0x8", + "Unit": "IRP" + }, + { + "BriefDescription": "AK Egress Allocations", + "EventCode": "0x0b", + "EventName": "UNC_I_TxC_AK_INSERTS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL DRS Egress Cycles Full", + "EventCode": "0x05", + "EventName": "UNC_I_TxC_BL_DRS_CYCLES_FULL", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL DRS Egress Inserts", + "EventCode": "0x02", + "EventName": "UNC_I_TxC_BL_DRS_INSERTS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL DRS Egress Occupancy", + "EventCode": "0x08", + "EventName": "UNC_I_TxC_BL_DRS_OCCUPANCY", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL NCB Egress Cycles Full", + "EventCode": "0x06", + "EventName": "UNC_I_TxC_BL_NCB_CYCLES_FULL", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL NCB Egress Inserts", + "EventCode": "0x03", + "EventName": "UNC_I_TxC_BL_NCB_INSERTS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL NCB Egress Occupancy", + "EventCode": "0x09", + "EventName": "UNC_I_TxC_BL_NCB_OCCUPANCY", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL NCS Egress Cycles Full", + "EventCode": "0x07", + "EventName": "UNC_I_TxC_BL_NCS_CYCLES_FULL", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL NCS Egress Inserts", + "EventCode": "0x04", + "EventName": "UNC_I_TxC_BL_NCS_INSERTS", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "BL NCS Egress Occupancy", + "EventCode": "0x0a", + "EventName": "UNC_I_TxC_BL_NCS_OCCUPANCY", + "PerPkg": "1", + "Unit": "IRP" + }, + { + "BriefDescription": "UNC_I_TxR2_AD01_STALL_CREDIT_CYCLES", + "EventCode": "0x1c", + "EventName": "UNC_I_TxR2_AD01_STALL_CREDIT_CYCLES", + "PerPkg": "1", + "PublicDescription": ": Counts the number times when it is not possible to issue a request to the M2PCIe because there are no Egress Credits available on AD0, A1 or AD0AD1 both. Stalls on both AD0 and AD1 will count as 2", + "Unit": "IRP" + }, + { + "BriefDescription": "No AD0 Egress Credits Stalls", + "EventCode": "0x1a", + "EventName": "UNC_I_TxR2_AD0_STALL_CREDIT_CYCLES", + "PerPkg": "1", + "PublicDescription": "No AD0 Egress Credits Stalls : Counts the number times when it is not possible to issue a request to the M2PCIe because there are no AD0 Egress Credits available.", + "Unit": "IRP" + }, + { + "BriefDescription": "No AD1 Egress Credits Stalls", + "EventCode": "0x1b", + "EventName": "UNC_I_TxR2_AD1_STALL_CREDIT_CYCLES", + "PerPkg": "1", + "PublicDescription": "No AD1 Egress Credits Stalls : Counts the number times when it is not possible to issue a request to the M2PCIe because there are no AD1 Egress Credits available.", + "Unit": "IRP" + }, + { + "BriefDescription": "No BL Egress Credit Stalls", + "EventCode": "0x1d", + "EventName": "UNC_I_TxR2_BL_STALL_CREDIT_CYCLES", + "PerPkg": "1", + "PublicDescription": "No BL Egress Credit Stalls : Counts the number times when it is not possible to issue data to the R2PCIe because there are no BL Egress Credits available.", + "Unit": "IRP" + }, + { + "BriefDescription": "Outbound Read Requests", + "EventCode": "0x0d", + "EventName": "UNC_I_TxS_DATA_INSERTS_NCB", + "PerPkg": "1", + "PublicDescription": "Outbound Read Requests : Counts the number of requests issued to the switch (towards the devices).", + "Unit": "IRP" + }, + { + "BriefDescription": "Outbound Read Requests", + "EventCode": "0x0e", + "EventName": "UNC_I_TxS_DATA_INSERTS_NCS", + "PerPkg": "1", + "PublicDescription": "Outbound Read Requests : Counts the number of requests issued to the switch (towards the devices).", + "Unit": "IRP" + }, + { + "BriefDescription": "Outbound Request Queue Occupancy", + "EventCode": "0x0c", + "EventName": "UNC_I_TxS_REQUEST_OCCUPANCY", + "PerPkg": "1", + "PublicDescription": "Outbound Request Queue Occupancy : Accumulates the number of outstanding outbound requests from the IRP to the switch (towards the devices). This can be used in conjunction with the allocations event in order to calculate average latency of outbound requests.", + "Unit": "IRP" + }, + { + "BriefDescription": "M2M Clockticks", + "EventCode": "0x01", + "EventName": "UNC_M2M_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Clockticks of the mesh to memory (M2M)", + "Unit": "M2M" + }, + { + "BriefDescription": "CMS Clockticks", + "EventCode": "0xc0", + "EventName": "UNC_M2M_CMS_CLOCKTICKS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Cycles when direct to core mode (which bypasses the CHA) was disabled", + "EventCode": "0x17", + "EventName": "UNC_M2M_DIRECT2CORE_NOT_TAKEN_DIRSTATE", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "M2M" + }, + { + "BriefDescription": "Cycles when direct to core mode, which bypasses the CHA, was disabled : Non Cisgress", + "EventCode": "0x17", + "EventName": "UNC_M2M_DIRECT2CORE_NOT_TAKEN_DIRSTATE.NON_CISGRESS", + "PerPkg": "1", + "PublicDescription": "Cycles when direct to core mode, which bypasses the CHA, was disabled : Non Cisgress : Counts the number of time non cisgress D2C was not honoured by egress due to directory state constraints", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Counts the time when FM didn't do d2c for fill reads (cross tile case)", + "EventCode": "0x4a", + "EventName": "UNC_M2M_DIRECT2CORE_NOT_TAKEN_NOTFORKED", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of reads in which direct to core transaction were overridden", + "EventCode": "0x18", + "EventName": "UNC_M2M_DIRECT2CORE_TXN_OVERRIDE", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of reads in which direct to core transaction was overridden : Cisgress", + "EventCode": "0x18", + "EventName": "UNC_M2M_DIRECT2CORE_TXN_OVERRIDE.CISGRESS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of reads in which direct to core transaction was overridden : 2LM Hit?", + "EventCode": "0x18", + "EventName": "UNC_M2M_DIRECT2CORE_TXN_OVERRIDE.PMM_HIT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of times a direct to UPI transaction was overridden.", + "EventCode": "0x1C", + "EventName": "UNC_M2M_DIRECT2UPITXN_OVERRIDE.PMM_HIT", + "PerPkg": "1", + "PublicDescription": "Number of times a direct to UPI transaction was overridden. : Counts the number of times D2K wasn't honored even though the incoming request had d2k set", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of reads in which direct to Intel UPI transactions were overridden", + "EventCode": "0x1b", + "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_CREDITS", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "M2M" + }, + { + "BriefDescription": "Cycles when direct to Intel UPI was disabled", + "EventCode": "0x1a", + "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_DIRSTATE", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "M2M" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Cisgress D2U Ignored", + "EventCode": "0x1A", + "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_DIRSTATE.CISGRESS", + "PerPkg": "1", + "PublicDescription": "Cycles when Direct2UPI was Disabled : Cisgress D2U Ignored : Counts cisgress d2K that was not honored due to directory constraints", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Egress Ignored D2U", + "EventCode": "0x1A", + "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_DIRSTATE.EGRESS", + "PerPkg": "1", + "PublicDescription": "Cycles when Direct2UPI was Disabled : Egress Ignored D2U : Counts the number of time D2K was not honoured by egress due to directory state constraints", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Non Cisgress D2U Ignored", + "EventCode": "0x1A", + "EventName": "UNC_M2M_DIRECT2UPI_NOT_TAKEN_DIRSTATE.NON_CISGRESS", + "PerPkg": "1", + "PublicDescription": "Cycles when Direct2UPI was Disabled : Non Cisgress D2U Ignored : Counts non cisgress d2K that was not honored due to directory constraints", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Messages sent direct to the Intel UPI", + "EventCode": "0x19", + "EventName": "UNC_M2M_DIRECT2UPI_TAKEN", + "PerPkg": "1", + "PublicDescription": "Counts the number of times egress did D2K (Direct to KTI)", + "UMask": "0x7", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of reads that a message sent direct2 Intel UPI was overridden", + "EventCode": "0x1c", + "EventName": "UNC_M2M_DIRECT2UPI_TXN_OVERRIDE", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2M" + }, + { + "BriefDescription": "Number of times a direct to UPI transaction was overridden.", + "EventCode": "0x1C", + "EventName": "UNC_M2M_DIRECT2UPI_TXN_OVERRIDE.CISGRESS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in A State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.CLEAN_A", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in I State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.CLEAN_I", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in L State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.CLEAN_P", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in S State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.CLEAN_S", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in A State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.DIRTY_A", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in I State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.DIRTY_I", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in L State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.DIRTY_P", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in S State", + "EventCode": "0x1d", + "EventName": "UNC_M2M_DIRECTORY_HIT.DIRTY_S", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookups (any state found)", + "EventCode": "0x20", + "EventName": "UNC_M2M_DIRECTORY_LOOKUP.ANY", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with any directory to non persistent memory", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookups (cacheline found in A state)", + "EventCode": "0x20", + "EventName": "UNC_M2M_DIRECTORY_LOOKUP.STATE_A", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with directory A to non persistent memory", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookup (cacheline found in I state)", + "EventCode": "0x20", + "EventName": "UNC_M2M_DIRECTORY_LOOKUP.STATE_I", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with directory I to non persistent memory", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookup (cacheline found in S state)", + "EventCode": "0x20", + "EventName": "UNC_M2M_DIRECTORY_LOOKUP.STATE_S", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with directory S to non persistent memory", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in A State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.CLEAN_A", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in I State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.CLEAN_I", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in L State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.CLEAN_P", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in S State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.CLEAN_S", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in A State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.DIRTY_A", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in I State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.DIRTY_I", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in L State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.DIRTY_P", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in S State", + "EventCode": "0x1e", + "EventName": "UNC_M2M_DIRECTORY_MISS.DIRTY_S", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from A to I", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.A2I", + "PerPkg": "1", + "UMask": "0x320", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from A to S", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.A2S", + "PerPkg": "1", + "UMask": "0x340", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from/to Any state", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.ANY", + "PerPkg": "1", + "UMask": "0x301", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.A_TO_I_HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from A to I to non persistent memory (DRAM or HBM)", + "UMask": "0x120", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.A_TO_I_MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from A to I to non persistent memory (DRAM or HBM)", + "UMask": "0x220", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.A_TO_S_HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from A to S to non persistent memory (DRAM or HBM)", + "UMask": "0x140", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.A_TO_S_MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from A to S to non persistent memory (DRAM or HBM)", + "UMask": "0x240", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts any 1lm or 2lm hit data return that would result in directory update to non persistent memory (DRAM or HBM)", + "UMask": "0x101", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from I to A", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.I2A", + "PerPkg": "1", + "UMask": "0x304", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from I to S", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.I2S", + "PerPkg": "1", + "UMask": "0x302", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.I_TO_A_HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from I to A to non persistent memory (DRAM or HBM)", + "UMask": "0x104", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.I_TO_A_MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from I to A to non persistent memory (DRAM or HBM)", + "UMask": "0x204", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.I_TO_S_HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from I to S to non persistent memory (DRAM or HBM)", + "UMask": "0x102", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.I_TO_S_MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from I to S to non persistent memory (DRAM or HBM)", + "UMask": "0x202", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts any 2lm miss data return that would result in directory update to non persistent memory (DRAM or HBM)", + "UMask": "0x201", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from S to A", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.S2A", + "PerPkg": "1", + "UMask": "0x310", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from S to I", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.S2I", + "PerPkg": "1", + "UMask": "0x308", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.S_TO_A_HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from S to A to non persistent memory (DRAM or HBM)", + "UMask": "0x110", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.S_TO_A_MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from S to A to non persistent memory (DRAM or HBM)", + "UMask": "0x210", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.S_TO_I_HIT_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from S to I to non persistent memory (DRAM or HBM)", + "UMask": "0x108", + "Unit": "M2M" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2M_DIRECTORY_UPDATE.S_TO_I_MISS_NON_PMM", + "PerPkg": "1", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from S to I to non persistent memory (DRAM or HBM)", + "UMask": "0x208", + "Unit": "M2M" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Down", + "EventCode": "0xba", + "EventName": "UNC_M2M_EGRESS_ORDERING.IV_SNOOPGO_DN", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Down : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x80000004", + "Unit": "M2M" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Up", + "EventCode": "0xba", + "EventName": "UNC_M2M_EGRESS_ORDERING.IV_SNOOPGO_UP", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Up : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x80000001", + "Unit": "M2M" + }, + { + "BriefDescription": "Count when Starve Glocab counter is at 7", + "EventCode": "0x44", + "EventName": "UNC_M2M_IGR_STARVE_WINNER.MASK7", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2M" + }, + { + "BriefDescription": "Reads to iMC issued", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.ALL", + "PerPkg": "1", + "UMask": "0x304", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0.TO_NM1LM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0.TO_NM1LM", + "PerPkg": "1", + "UMask": "0x108", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0.TO_NMCache", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0.TO_NMCache", + "PerPkg": "1", + "UMask": "0x110", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_ALL", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x104", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_FROM_TGR", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_FROM_TGR", + "PerPkg": "1", + "UMask": "0x140", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_ISOCH", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_ISOCH", + "PerPkg": "1", + "UMask": "0x102", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_NORMAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x101", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_TO_DDR_AS_CACHE", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_TO_DDR_AS_CACHE", + "PerPkg": "1", + "UMask": "0x110", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_TO_DDR_AS_MEM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_TO_DDR_AS_MEM", + "PerPkg": "1", + "UMask": "0x108", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH0_TO_PMM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH0_TO_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x120", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1.TO_NM1LM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1.TO_NM1LM", + "PerPkg": "1", + "UMask": "0x208", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1.TO_NMCache", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1.TO_NMCache", + "PerPkg": "1", + "UMask": "0x210", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_ALL", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x204", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_FROM_TGR", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_FROM_TGR", + "PerPkg": "1", + "UMask": "0x240", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_ISOCH", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_ISOCH", + "PerPkg": "1", + "UMask": "0x202", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_NORMAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x201", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_TO_DDR_AS_CACHE", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_TO_DDR_AS_CACHE", + "PerPkg": "1", + "UMask": "0x210", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_TO_DDR_AS_MEM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_TO_DDR_AS_MEM", + "PerPkg": "1", + "UMask": "0x208", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.CH1_TO_PMM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.CH1_TO_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x220", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.FROM_TGR", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.FROM_TGR", + "PerPkg": "1", + "UMask": "0x340", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.ISOCH", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.ISOCH", + "PerPkg": "1", + "UMask": "0x302", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.NORMAL", + "PerPkg": "1", + "UMask": "0x301", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.TO_DDR_AS_CACHE", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.TO_DDR_AS_CACHE", + "PerPkg": "1", + "UMask": "0x310", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.TO_DDR_AS_MEM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.TO_DDR_AS_MEM", + "PerPkg": "1", + "UMask": "0x308", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.TO_NM1LM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.TO_NM1LM", + "PerPkg": "1", + "UMask": "0x308", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.TO_NMCACHE", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.TO_NMCACHE", + "PerPkg": "1", + "UMask": "0x310", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_READS.TO_PMM", + "EventCode": "0x24", + "EventName": "UNC_M2M_IMC_READS.TO_PMM", + "PerPkg": "1", + "UMask": "0x320", + "Unit": "M2M" + }, + { + "BriefDescription": "All Writes - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.ALL", + "PerPkg": "1", + "UMask": "0x1810", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0.NI", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_WRITES.CH0_ALL", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x810", + "Unit": "M2M" + }, + { + "BriefDescription": "From TGR - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_FROM_TGR", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_WRITES.CH0_FULL", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_FULL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x801", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_WRITES.CH0_FULL_ISOCH", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_FULL_ISOCH", + "PerPkg": "1", + "UMask": "0x804", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_NI", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive Miss - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_NI_MISS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_WRITES.CH0_PARTIAL", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_PARTIAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x802", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_WRITES.CH0_PARTIAL_ISOCH", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_PARTIAL_ISOCH", + "PerPkg": "1", + "UMask": "0x808", + "Unit": "M2M" + }, + { + "BriefDescription": "DDR, acting as Cache - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_TO_DDR_AS_CACHE", + "PerPkg": "1", + "UMask": "0x840", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_IMC_WRITES.CH0_TO_DDR_AS_MEM", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_TO_DDR_AS_MEM", + "PerPkg": "1", + "UMask": "0x820", + "Unit": "M2M" + }, + { + "BriefDescription": "PMM - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH0_TO_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "PMM - Ch0 : Counts all PMM dimm writes requests(full line and partial) sent from M2M to iMC", + "UMask": "0x880", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1.NI", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "All Writes - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1010", + "Unit": "M2M" + }, + { + "BriefDescription": "From TGR - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_FROM_TGR", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Full Line Non-ISOCH - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_FULL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1001", + "Unit": "M2M" + }, + { + "BriefDescription": "ISOCH Full Line - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_FULL_ISOCH", + "PerPkg": "1", + "UMask": "0x1004", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_NI", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive Miss - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_NI_MISS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Partial Non-ISOCH - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_PARTIAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1002", + "Unit": "M2M" + }, + { + "BriefDescription": "ISOCH Partial - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_PARTIAL_ISOCH", + "PerPkg": "1", + "UMask": "0x1008", + "Unit": "M2M" + }, + { + "BriefDescription": "DDR, acting as Cache - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_TO_DDR_AS_CACHE", + "PerPkg": "1", + "UMask": "0x1040", + "Unit": "M2M" + }, + { + "BriefDescription": "DDR - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_TO_DDR_AS_MEM", + "PerPkg": "1", + "UMask": "0x1020", + "Unit": "M2M" + }, + { + "BriefDescription": "PMM - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.CH1_TO_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "PMM - Ch1 : Counts all PMM dimm writes requests(full line and partial) sent from M2M to iMC", + "UMask": "0x1080", + "Unit": "M2M" + }, + { + "BriefDescription": "From TGR - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.FROM_TGR", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Full Non-ISOCH - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.FULL", + "PerPkg": "1", + "UMask": "0x1801", + "Unit": "M2M" + }, + { + "BriefDescription": "ISOCH Full Line - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.FULL_ISOCH", + "PerPkg": "1", + "UMask": "0x1804", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.NI", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Non-Inclusive Miss - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.NI_MISS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Partial Non-ISOCH - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.PARTIAL", + "PerPkg": "1", + "UMask": "0x1802", + "Unit": "M2M" + }, + { + "BriefDescription": "ISOCH Partial - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.PARTIAL_ISOCH", + "PerPkg": "1", + "UMask": "0x1808", + "Unit": "M2M" + }, + { + "BriefDescription": "DDR, acting as Cache - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.TO_DDR_AS_CACHE", + "PerPkg": "1", + "UMask": "0x1840", + "Unit": "M2M" + }, + { + "BriefDescription": "DDR - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.TO_DDR_AS_MEM", + "PerPkg": "1", + "UMask": "0x1820", + "Unit": "M2M" + }, + { + "BriefDescription": "PMM - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2M_IMC_WRITES.TO_PMM", + "PerPkg": "1", + "UMask": "0x1880", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_PREFCAM_CIS_DROPS", + "EventCode": "0x5c", + "EventName": "UNC_M2M_PREFCAM_CIS_DROPS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2M_PREFCAM_DEMAND_DROPS.CH0_UPI", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2M_PREFCAM_DEMAND_DROPS.CH0_XPT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2M_PREFCAM_DEMAND_DROPS.CH1_UPI", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2M_PREFCAM_DEMAND_DROPS.CH1_XPT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Data Prefetches Dropped : UPI - All Channels", + "EventCode": "0x58", + "EventName": "UNC_M2M_PREFCAM_DEMAND_DROPS.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "M2M" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2M_PREFCAM_DEMAND_DROPS.XPT_ALLCH", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "M2M" + }, + { + "BriefDescription": ": UPI - All Channels", + "EventCode": "0x5d", + "EventName": "UNC_M2M_PREFCAM_DEMAND_MERGE.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "M2M" + }, + { + "BriefDescription": ": XPT - All Channels", + "EventCode": "0x5d", + "EventName": "UNC_M2M_PREFCAM_DEMAND_MERGE.XPT_ALLCH", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "M2M" + }, + { + "BriefDescription": "Demands Not Merged with CAMed Prefetches", + "EventCode": "0x5E", + "EventName": "UNC_M2M_PREFCAM_DEMAND_NO_MERGE.RD_MERGED", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2M" + }, + { + "BriefDescription": "Demands Not Merged with CAMed Prefetches", + "EventCode": "0x5E", + "EventName": "UNC_M2M_PREFCAM_DEMAND_NO_MERGE.WR_MERGED", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2M" + }, + { + "BriefDescription": "Demands Not Merged with CAMed Prefetches", + "EventCode": "0x5E", + "EventName": "UNC_M2M_PREFCAM_DEMAND_NO_MERGE.WR_SQUASHED", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - Ch 0", + "EventCode": "0x56", + "EventName": "UNC_M2M_PREFCAM_INSERTS.CH0_UPI", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - Ch 0", + "EventCode": "0x56", + "EventName": "UNC_M2M_PREFCAM_INSERTS.CH0_XPT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - Ch 1", + "EventCode": "0x56", + "EventName": "UNC_M2M_PREFCAM_INSERTS.CH1_UPI", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - Ch 1", + "EventCode": "0x56", + "EventName": "UNC_M2M_PREFCAM_INSERTS.CH1_XPT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - All Channels", + "EventCode": "0x56", + "EventName": "UNC_M2M_PREFCAM_INSERTS.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - All Channels", + "EventCode": "0x56", + "EventName": "UNC_M2M_PREFCAM_INSERTS.XPT_ALLCH", + "PerPkg": "1", + "PublicDescription": "Prefetch CAM Inserts : XPT -All Channels", + "UMask": "0x5", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : All Channels", + "EventCode": "0x54", + "EventName": "UNC_M2M_PREFCAM_OCCUPANCY.ALLCH", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : Channel 0", + "EventCode": "0x54", + "EventName": "UNC_M2M_PREFCAM_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : Channel 1", + "EventCode": "0x54", + "EventName": "UNC_M2M_PREFCAM_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "All Channels", + "EventCode": "0x5F", + "EventName": "UNC_M2M_PREFCAM_RESP_MISS.ALLCH", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2M" + }, + { + "BriefDescription": ": Channel 0", + "EventCode": "0x5f", + "EventName": "UNC_M2M_PREFCAM_RESP_MISS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": ": Channel 1", + "EventCode": "0x5f", + "EventName": "UNC_M2M_PREFCAM_RESP_MISS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_PREFCAM_RxC_DEALLOCS.1LM_POSTED", + "EventCode": "0x62", + "EventName": "UNC_M2M_PREFCAM_RxC_DEALLOCS.1LM_POSTED", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_PREFCAM_RxC_DEALLOCS.CIS", + "EventCode": "0x62", + "EventName": "UNC_M2M_PREFCAM_RxC_DEALLOCS.CIS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_PREFCAM_RxC_DEALLOCS.PMM_MEMMODE_ACCEPT", + "EventCode": "0x62", + "EventName": "UNC_M2M_PREFCAM_RxC_DEALLOCS.PMM_MEMMODE_ACCEPT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_PREFCAM_RxC_DEALLOCS.SQUASHED", + "EventCode": "0x62", + "EventName": "UNC_M2M_PREFCAM_RxC_DEALLOCS.SQUASHED", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "AD Ingress (from CMS) Occupancy - Prefetches", + "EventCode": "0x60", + "EventName": "UNC_M2M_PREFCAM_RxC_OCCUPANCY", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "AD Ingress (from CMS) : AD Ingress (from CMS) Allocations", + "EventCode": "0x02", + "EventName": "UNC_M2M_RxC_AD_INSERTS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "AD Ingress (from CMS) Occupancy", + "EventCode": "0x03", + "EventName": "UNC_M2M_RxC_AD_OCCUPANCY", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Clean NearMem Read Hit", + "EventCode": "0x1F", + "EventName": "UNC_M2M_TAG_HIT.NM_RD_HIT_CLEAN", + "PerPkg": "1", + "PublicDescription": "Counts clean full line read hits (reads and RFOs).", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Dirty NearMem Read Hit", + "EventCode": "0x1F", + "EventName": "UNC_M2M_TAG_HIT.NM_RD_HIT_DIRTY", + "PerPkg": "1", + "PublicDescription": "Counts dirty full line read hits (reads and RFOs).", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Tag Hit : Clean NearMem Underfill Hit", + "EventCode": "0x1F", + "EventName": "UNC_M2M_TAG_HIT.NM_UFILL_HIT_CLEAN", + "PerPkg": "1", + "PublicDescription": "Tag Hit indicates when a request sent to the iMC hit in Near Memory. : Counts clean underfill hits due to a partial write", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Tag Hit : Dirty NearMem Underfill Hit", + "EventCode": "0x1F", + "EventName": "UNC_M2M_TAG_HIT.NM_UFILL_HIT_DIRTY", + "PerPkg": "1", + "PublicDescription": "Tag Hit indicates when a request sent to the iMC hit in Near Memory. : Counts dirty underfill read hits due to a partial write", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "UNC_M2M_TAG_MISS", + "EventCode": "0x4b", + "EventName": "UNC_M2M_TAG_MISS", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2M" + }, + { + "BriefDescription": "Number AD Ingress Credits", + "EventCode": "0x2e", + "EventName": "UNC_M2M_TGR_AD_CREDITS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Number BL Ingress Credits", + "EventCode": "0x2f", + "EventName": "UNC_M2M_TGR_BL_CREDITS", + "PerPkg": "1", + "Unit": "M2M" + }, + { + "BriefDescription": "Tracker Inserts : Channel 0", + "EventCode": "0x32", + "EventName": "UNC_M2M_TRACKER_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x104", + "Unit": "M2M" + }, + { + "BriefDescription": "Tracker Inserts : Channel 1", + "EventCode": "0x32", + "EventName": "UNC_M2M_TRACKER_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x204", + "Unit": "M2M" + }, + { + "BriefDescription": "Tracker Occupancy : Channel 0", + "EventCode": "0x33", + "EventName": "UNC_M2M_TRACKER_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Tracker Occupancy : Channel 1", + "EventCode": "0x33", + "EventName": "UNC_M2M_TRACKER_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "WPQ Flush : Channel 0", + "EventCode": "0x42", + "EventName": "UNC_M2M_WPQ_FLUSH.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "WPQ Flush : Channel 1", + "EventCode": "0x42", + "EventName": "UNC_M2M_WPQ_FLUSH.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "M2M->iMC WPQ Cycles w/Credits - Regular : Channel 0", + "EventCode": "0x37", + "EventName": "UNC_M2M_WPQ_NO_REG_CRD.CHN0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "M2M->iMC WPQ Cycles w/Credits - Regular : Channel 1", + "EventCode": "0x37", + "EventName": "UNC_M2M_WPQ_NO_REG_CRD.CHN1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "M2M->iMC WPQ Cycles w/Credits - Special : Channel 0", + "EventCode": "0x38", + "EventName": "UNC_M2M_WPQ_NO_SPEC_CRD.CHN0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "M2M->iMC WPQ Cycles w/Credits - Special : Channel 1", + "EventCode": "0x38", + "EventName": "UNC_M2M_WPQ_NO_SPEC_CRD.CHN1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Inserts : Channel 0", + "EventCode": "0x40", + "EventName": "UNC_M2M_WR_TRACKER_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Inserts : Channel 1", + "EventCode": "0x40", + "EventName": "UNC_M2M_WR_TRACKER_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Cycles Not Empty : Channel 0", + "EventCode": "0x35", + "EventName": "UNC_M2M_WR_TRACKER_NE.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Cycles Not Empty : Channel 1", + "EventCode": "0x35", + "EventName": "UNC_M2M_WR_TRACKER_NE.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Cycles Not Empty : Mirror", + "EventCode": "0x35", + "EventName": "UNC_M2M_WR_TRACKER_NE.MIRR", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Cycles Not Empty", + "EventCode": "0x35", + "EventName": "UNC_M2M_WR_TRACKER_NE.MIRR_NONTGR", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Cycles Not Empty", + "EventCode": "0x35", + "EventName": "UNC_M2M_WR_TRACKER_NE.MIRR_PWR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Non-Posted Inserts : Channel 0", + "EventCode": "0x4d", + "EventName": "UNC_M2M_WR_TRACKER_NONPOSTED_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Non-Posted Inserts : Channel 1", + "EventCode": "0x4d", + "EventName": "UNC_M2M_WR_TRACKER_NONPOSTED_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Non-Posted Occupancy : Channel 0", + "EventCode": "0x4c", + "EventName": "UNC_M2M_WR_TRACKER_NONPOSTED_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Non-Posted Occupancy : Channel 1", + "EventCode": "0x4c", + "EventName": "UNC_M2M_WR_TRACKER_NONPOSTED_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Posted Inserts : Channel 0", + "EventCode": "0x48", + "EventName": "UNC_M2M_WR_TRACKER_POSTED_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Posted Inserts : Channel 1", + "EventCode": "0x48", + "EventName": "UNC_M2M_WR_TRACKER_POSTED_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Posted Occupancy : Channel 0", + "EventCode": "0x47", + "EventName": "UNC_M2M_WR_TRACKER_POSTED_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2M" + }, + { + "BriefDescription": "Write Tracker Posted Occupancy : Channel 1", + "EventCode": "0x47", + "EventName": "UNC_M2M_WR_TRACKER_POSTED_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2M" + }, + { + "BriefDescription": "CBox AD Credits Empty : Requests", + "EventCode": "0x22", + "EventName": "UNC_M3UPI_CHA_AD_CREDITS_EMPTY.REQ", + "PerPkg": "1", + "PublicDescription": "CBox AD Credits Empty : Requests : No credits available to send to Cbox on the AD Ring (covers higher CBoxes)", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "CBox AD Credits Empty : Snoops", + "EventCode": "0x22", + "EventName": "UNC_M3UPI_CHA_AD_CREDITS_EMPTY.SNP", + "PerPkg": "1", + "PublicDescription": "CBox AD Credits Empty : Snoops : No credits available to send to Cbox on the AD Ring (covers higher CBoxes)", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "CBox AD Credits Empty : VNA Messages", + "EventCode": "0x22", + "EventName": "UNC_M3UPI_CHA_AD_CREDITS_EMPTY.VNA", + "PerPkg": "1", + "PublicDescription": "CBox AD Credits Empty : VNA Messages : No credits available to send to Cbox on the AD Ring (covers higher CBoxes)", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "CBox AD Credits Empty : Writebacks", + "EventCode": "0x22", + "EventName": "UNC_M3UPI_CHA_AD_CREDITS_EMPTY.WB", + "PerPkg": "1", + "PublicDescription": "CBox AD Credits Empty : Writebacks : No credits available to send to Cbox on the AD Ring (covers higher CBoxes)", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M3UPI Clockticks", + "EventCode": "0x01", + "EventName": "UNC_M3UPI_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of M2UPI clock cycles while the event is enabled", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M3UPI CMS Clockticks", + "EventCode": "0xc0", + "EventName": "UNC_M3UPI_CMS_CLOCKTICKS", + "PerPkg": "1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "D2C Sent", + "EventCode": "0x2b", + "EventName": "UNC_M3UPI_D2C_SENT", + "PerPkg": "1", + "PublicDescription": "D2C Sent : Count cases BL sends direct to core", + "Unit": "M3UPI" + }, + { + "BriefDescription": "D2U Sent", + "EventCode": "0x2a", + "EventName": "UNC_M3UPI_D2U_SENT", + "PerPkg": "1", + "PublicDescription": "D2U Sent : Cases where SMI3 sends D2U command", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Down", + "EventCode": "0xba", + "EventName": "UNC_M3UPI_EGRESS_ORDERING.IV_SNOOPGO_DN", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Down : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Up", + "EventCode": "0xba", + "EventName": "UNC_M3UPI_EGRESS_ORDERING.IV_SNOOPGO_UP", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Up : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : IIO0 and IIO1 share the same ring destination. (1 VN0 credit only)", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.IIO1_NCB", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : IIO0 and IIO1 share the same ring destination. (1 VN0 credit only) : No vn0 and vna credits available to send to M2", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : IIO2", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.IIO2_NCB", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : IIO2 : No vn0 and vna credits available to send to M2", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : IIO3", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.IIO3_NCB", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : IIO3 : No vn0 and vna credits available to send to M2", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : IIO4", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.IIO4_NCB", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : IIO4 : No vn0 and vna credits available to send to M2", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : IIO5", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.IIO5_NCB", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : IIO5 : No vn0 and vna credits available to send to M2", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : All IIO targets for NCS are in single mask. ORs them together", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.NCS", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : All IIO targets for NCS are in single mask. ORs them together : No vn0 and vna credits available to send to M2", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : Selected M2p BL NCS credits", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.NCS_SEL", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : Selected M2p BL NCS credits : No vn0 and vna credits available to send to M2", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "M2 BL Credits Empty : IIO5", + "EventCode": "0x23", + "EventName": "UNC_M3UPI_M2_BL_CREDITS_EMPTY.UBOX_NCB", + "PerPkg": "1", + "PublicDescription": "M2 BL Credits Empty : IIO5 : No vn0 and vna credits available to send to M2", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Multi Slot Flit Received : AD - Slot 0", + "EventCode": "0x3e", + "EventName": "UNC_M3UPI_MULTI_SLOT_RCVD.AD_SLOT0", + "PerPkg": "1", + "PublicDescription": "Multi Slot Flit Received : AD - Slot 0 : Multi slot flit received - S0, S1 and/or S2 populated (can use AK S0/S1 masks for AK allocations)", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Multi Slot Flit Received : AD - Slot 1", + "EventCode": "0x3e", + "EventName": "UNC_M3UPI_MULTI_SLOT_RCVD.AD_SLOT1", + "PerPkg": "1", + "PublicDescription": "Multi Slot Flit Received : AD - Slot 1 : Multi slot flit received - S0, S1 and/or S2 populated (can use AK S0/S1 masks for AK allocations)", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Multi Slot Flit Received : AD - Slot 2", + "EventCode": "0x3e", + "EventName": "UNC_M3UPI_MULTI_SLOT_RCVD.AD_SLOT2", + "PerPkg": "1", + "PublicDescription": "Multi Slot Flit Received : AD - Slot 2 : Multi slot flit received - S0, S1 and/or S2 populated (can use AK S0/S1 masks for AK allocations)", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Multi Slot Flit Received : AK - Slot 0", + "EventCode": "0x3e", + "EventName": "UNC_M3UPI_MULTI_SLOT_RCVD.AK_SLOT0", + "PerPkg": "1", + "PublicDescription": "Multi Slot Flit Received : AK - Slot 0 : Multi slot flit received - S0, S1 and/or S2 populated (can use AK S0/S1 masks for AK allocations)", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Multi Slot Flit Received : AK - Slot 2", + "EventCode": "0x3e", + "EventName": "UNC_M3UPI_MULTI_SLOT_RCVD.AK_SLOT2", + "PerPkg": "1", + "PublicDescription": "Multi Slot Flit Received : AK - Slot 2 : Multi slot flit received - S0, S1 and/or S2 populated (can use AK S0/S1 masks for AK allocations)", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Multi Slot Flit Received : BL - Slot 0", + "EventCode": "0x3e", + "EventName": "UNC_M3UPI_MULTI_SLOT_RCVD.BL_SLOT0", + "PerPkg": "1", + "PublicDescription": "Multi Slot Flit Received : BL - Slot 0 : Multi slot flit received - S0, S1 and/or S2 populated (can use AK S0/S1 masks for AK allocations)", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : REQ on AD", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.AD_REQ", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : REQ on AD : VN0 message requested but lost arbitration : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : RSP on AD", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.AD_RSP", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : RSP on AD : VN0 message requested but lost arbitration : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : SNP on AD", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.AD_SNP", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : SNP on AD : VN0 message requested but lost arbitration : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : NCB on BL", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.BL_NCB", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : NCB on BL : VN0 message requested but lost arbitration : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : NCS on BL", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.BL_NCS", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : NCS on BL : VN0 message requested but lost arbitration : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : RSP on BL", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.BL_RSP", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : RSP on BL : VN0 message requested but lost arbitration : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN0 : WB on BL", + "EventCode": "0x4b", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN0.BL_WB", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN0 : WB on BL : VN0 message requested but lost arbitration : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : REQ on AD", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.AD_REQ", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : REQ on AD : VN1 message requested but lost arbitration : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : RSP on AD", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.AD_RSP", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : RSP on AD : VN1 message requested but lost arbitration : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : SNP on AD", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.AD_SNP", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : SNP on AD : VN1 message requested but lost arbitration : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : NCB on BL", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.BL_NCB", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : NCB on BL : VN1 message requested but lost arbitration : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : NCS on BL", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.BL_NCS", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : NCS on BL : VN1 message requested but lost arbitration : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : RSP on BL", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.BL_RSP", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : RSP on BL : VN1 message requested but lost arbitration : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Lost Arb for VN1 : WB on BL", + "EventCode": "0x4c", + "EventName": "UNC_M3UPI_RxC_ARB_LOST_VN1.BL_WB", + "PerPkg": "1", + "PublicDescription": "Lost Arb for VN1 : WB on BL : VN1 message requested but lost arbitration : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : AD, BL Parallel Win VN0", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.ADBL_PARALLEL_WIN_VN0", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : AD, BL Parallel Win VN0 : AD and BL messages won arbitration concurrently / in parallel", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : AD, BL Parallel Win VN1", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.ADBL_PARALLEL_WIN_VN1", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : AD, BL Parallel Win VN1 : AD and BL messages won arbitration concurrently / in parallel", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : Max Parallel Win", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.ALL_PARALLEL_WIN", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : Max Parallel Win : VN0 and VN1 arbitration sub-pipelines both produced AD and BL winners (maximum possible parallel winners)", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : No Progress on Pending AD VN0", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.NO_PROG_AD_VN0", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : No Progress on Pending AD VN0 : Arbitration stage made no progress on pending ad vn0 messages because slotting stage cannot accept new message", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : No Progress on Pending AD VN1", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.NO_PROG_AD_VN1", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : No Progress on Pending AD VN1 : Arbitration stage made no progress on pending ad vn1 messages because slotting stage cannot accept new message", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : No Progress on Pending BL VN0", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.NO_PROG_BL_VN0", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : No Progress on Pending BL VN0 : Arbitration stage made no progress on pending bl vn0 messages because slotting stage cannot accept new message", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : No Progress on Pending BL VN1", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.NO_PROG_BL_VN1", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : No Progress on Pending BL VN1 : Arbitration stage made no progress on pending bl vn1 messages because slotting stage cannot accept new message", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Arb Miscellaneous : VN0, VN1 Parallel Win", + "EventCode": "0x4d", + "EventName": "UNC_M3UPI_RxC_ARB_MISC.VN01_PARALLEL_WIN", + "PerPkg": "1", + "PublicDescription": "Arb Miscellaneous : VN0, VN1 Parallel Win : VN0 and VN1 arbitration sub-pipelines had parallel winners (at least one AD or BL on each side)", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : REQ on AD", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.AD_REQ", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : REQ on AD : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : RSP on AD", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.AD_RSP", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : RSP on AD : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : SNP on AD", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.AD_SNP", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : SNP on AD : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : NCB on BL", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.BL_NCB", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : NCB on BL : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : NCS on BL", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.BL_NCS", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : NCS on BL : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : RSP on BL", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.BL_RSP", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : RSP on BL : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN0 : WB on BL", + "EventCode": "0x47", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN0.BL_WB", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN0 : WB on BL : VN0 message is blocked from requesting arbitration due to lack of remote UPI credits : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : REQ on AD", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.AD_REQ", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : REQ on AD : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : RSP on AD", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.AD_RSP", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : RSP on AD : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : SNP on AD", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.AD_SNP", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : SNP on AD : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : NCB on BL", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.BL_NCB", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : NCB on BL : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : NCS on BL", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.BL_NCS", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : NCS on BL : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : RSP on BL", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.BL_RSP", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : RSP on BL : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "No Credits to Arb for VN1 : WB on BL", + "EventCode": "0x48", + "EventName": "UNC_M3UPI_RxC_ARB_NOCRD_VN1.BL_WB", + "PerPkg": "1", + "PublicDescription": "No Credits to Arb for VN1 : WB on BL : VN1 message is blocked from requesting arbitration due to lack of remote UPI credits : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : REQ on AD", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.AD_REQ", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : REQ on AD : VN0 message was not able to request arbitration while some other message won arbitration : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : RSP on AD", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.AD_RSP", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : RSP on AD : VN0 message was not able to request arbitration while some other message won arbitration : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : SNP on AD", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.AD_SNP", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : SNP on AD : VN0 message was not able to request arbitration while some other message won arbitration : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : NCB on BL", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.BL_NCB", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : NCB on BL : VN0 message was not able to request arbitration while some other message won arbitration : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : NCS on BL", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.BL_NCS", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : NCS on BL : VN0 message was not able to request arbitration while some other message won arbitration : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : RSP on BL", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.BL_RSP", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : RSP on BL : VN0 message was not able to request arbitration while some other message won arbitration : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN0 : WB on BL", + "EventCode": "0x49", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN0.BL_WB", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN0 : WB on BL : VN0 message was not able to request arbitration while some other message won arbitration : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : REQ on AD", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.AD_REQ", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : REQ on AD : VN1 message was not able to request arbitration while some other message won arbitration : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : RSP on AD", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.AD_RSP", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : RSP on AD : VN1 message was not able to request arbitration while some other message won arbitration : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : SNP on AD", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.AD_SNP", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : SNP on AD : VN1 message was not able to request arbitration while some other message won arbitration : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : NCB on BL", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.BL_NCB", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : NCB on BL : VN1 message was not able to request arbitration while some other message won arbitration : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : NCS on BL", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.BL_NCS", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : NCS on BL : VN1 message was not able to request arbitration while some other message won arbitration : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : RSP on BL", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.BL_RSP", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : RSP on BL : VN1 message was not able to request arbitration while some other message won arbitration : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Can't Arb for VN1 : WB on BL", + "EventCode": "0x4a", + "EventName": "UNC_M3UPI_RxC_ARB_NOREQ_VN1.BL_WB", + "PerPkg": "1", + "PublicDescription": "Can't Arb for VN1 : WB on BL : VN1 message was not able to request arbitration while some other message won arbitration : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Ingress Queue Bypasses : AD to Slot 0 on BL Arb", + "EventCode": "0x40", + "EventName": "UNC_M3UPI_RxC_BYPASSED.AD_S0_BL_ARB", + "PerPkg": "1", + "PublicDescription": "Ingress Queue Bypasses : AD to Slot 0 on BL Arb : Number of times message is bypassed around the Ingress Queue : AD is taking bypass to slot 0 of independent flit while bl message is in arbitration", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Ingress Queue Bypasses : AD to Slot 0 on Idle", + "EventCode": "0x40", + "EventName": "UNC_M3UPI_RxC_BYPASSED.AD_S0_IDLE", + "PerPkg": "1", + "PublicDescription": "Ingress Queue Bypasses : AD to Slot 0 on Idle : Number of times message is bypassed around the Ingress Queue : AD is taking bypass to slot 0 of independent flit while pipeline is idle", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Ingress Queue Bypasses : AD + BL to Slot 1", + "EventCode": "0x40", + "EventName": "UNC_M3UPI_RxC_BYPASSED.AD_S1_BL_SLOT", + "PerPkg": "1", + "PublicDescription": "Ingress Queue Bypasses : AD + BL to Slot 1 : Number of times message is bypassed around the Ingress Queue : AD is taking bypass to flit slot 1 while merging with bl message in same flit", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Ingress Queue Bypasses : AD + BL to Slot 2", + "EventCode": "0x40", + "EventName": "UNC_M3UPI_RxC_BYPASSED.AD_S2_BL_SLOT", + "PerPkg": "1", + "PublicDescription": "Ingress Queue Bypasses : AD + BL to Slot 2 : Number of times message is bypassed around the Ingress Queue : AD is taking bypass to flit slot 2 while merging with bl message in same flit", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Miscellaneous Credit Events : Any In BGF FIFO", + "EventCode": "0x5f", + "EventName": "UNC_M3UPI_RxC_CRD_MISC.ANY_BGF_FIFO", + "PerPkg": "1", + "PublicDescription": "Miscellaneous Credit Events : Any In BGF FIFO : Indication that at least one packet (flit) is in the bgf (fifo only)", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Miscellaneous Credit Events : Any in BGF Path", + "EventCode": "0x5f", + "EventName": "UNC_M3UPI_RxC_CRD_MISC.ANY_BGF_PATH", + "PerPkg": "1", + "PublicDescription": "Miscellaneous Credit Events : Any in BGF Path : Indication that at least one packet (flit) is in the bgf path (i.e. pipe to fifo)", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Miscellaneous Credit Events", + "EventCode": "0x5f", + "EventName": "UNC_M3UPI_RxC_CRD_MISC.LT1_FOR_D2K", + "PerPkg": "1", + "PublicDescription": "Miscellaneous Credit Events : d2k credit count is less than 1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Miscellaneous Credit Events", + "EventCode": "0x5f", + "EventName": "UNC_M3UPI_RxC_CRD_MISC.LT2_FOR_D2K", + "PerPkg": "1", + "PublicDescription": "Miscellaneous Credit Events : d2k credit count is less than 2", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Miscellaneous Credit Events : No D2K For Arb", + "EventCode": "0x5f", + "EventName": "UNC_M3UPI_RxC_CRD_MISC.VN0_NO_D2K_FOR_ARB", + "PerPkg": "1", + "PublicDescription": "Miscellaneous Credit Events : No D2K For Arb : VN0 BL RSP message was blocked from arbitration request due to lack of D2K CMP credit", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Miscellaneous Credit Events", + "EventCode": "0x5f", + "EventName": "UNC_M3UPI_RxC_CRD_MISC.VN1_NO_D2K_FOR_ARB", + "PerPkg": "1", + "PublicDescription": "Miscellaneous Credit Events : VN1 BL RSP message was blocked from arbitration request due to lack of D2K CMP credits", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy : Credits Consumed", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.CONSUMED", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : Credits Consumed : number of remote vna credits consumed per cycle", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy : D2K Credits", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.D2K_CRD", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : D2K Credits : D2K completion fifo credit occupancy (credits in use), accumulated across all cycles", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy : Packets in BGF FIFO", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.FLITS_IN_FIFO", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : Packets in BGF FIFO : Occupancy of m3upi ingress -> upi link layer bgf; packets (flits) in fifo", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy : Packets in BGF Path", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.FLITS_IN_PATH", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : Packets in BGF Path : Occupancy of m3upi ingress -> upi link layer bgf; packets (flits) in path (i.e. pipe to fifo or fifo)", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.P1P_FIFO", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : count of bl messages in pump-1-pending state, in completion fifo only", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.P1P_TOTAL", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : count of bl messages in pump-1-pending state, in marker table and in fifo", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy : Transmit Credits", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.TxQ_CRD", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : Transmit Credits : Link layer transmit queue credit occupancy (credits in use), accumulated across all cycles", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Credit Occupancy : VNA In Use", + "EventCode": "0x60", + "EventName": "UNC_M3UPI_RxC_CRD_OCC.VNA_IN_USE", + "PerPkg": "1", + "PublicDescription": "Credit Occupancy : VNA In Use : Remote UPI VNA credit occupancy (number of credits in use), accumulated across all cycles", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : REQ on AD", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.AD_REQ", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : REQ on AD : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : RSP on AD", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.AD_RSP", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : RSP on AD : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : SNP on AD", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.AD_SNP", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : SNP on AD : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : NCB on BL", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.BL_NCB", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : NCB on BL : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : NCS on BL", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.BL_NCS", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : NCS on BL : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : RSP on BL", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.BL_RSP", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : RSP on BL : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : WB on BL", + "EventCode": "0x43", + "EventName": "UNC_M3UPI_RxC_CYCLES_NE_VN0.BL_WB", + "PerPkg": "1", + "PublicDescription": "VN0 Ingress (from CMS) Queue - Cycles Not Empty : WB on BL : Counts the number of cycles when the UPI Ingress is not empty. This tracks one of the three rings that are used by the UPI agent. This can be used in conjunction with the UPI Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple ingress buffers can be tracked at a given time using multiple counters. : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Data Flit Not Sent : All", + "EventCode": "0x55", + "EventName": "UNC_M3UPI_RxC_DATA_FLITS_NOT_SENT.ALL", + "PerPkg": "1", + "PublicDescription": "Data Flit Not Sent : All : Data flit is ready for transmission but could not be sent : data flit is ready for transmission but could not be sent for any reason, e.g. low credits, low tsv, stall injection", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Data Flit Not Sent : No BGF Credits", + "EventCode": "0x55", + "EventName": "UNC_M3UPI_RxC_DATA_FLITS_NOT_SENT.NO_BGF", + "PerPkg": "1", + "PublicDescription": "Data Flit Not Sent : No BGF Credits : Data flit is ready for transmission but could not be sent", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Data Flit Not Sent : No TxQ Credits", + "EventCode": "0x55", + "EventName": "UNC_M3UPI_RxC_DATA_FLITS_NOT_SENT.NO_TXQ", + "PerPkg": "1", + "PublicDescription": "Data Flit Not Sent : No TxQ Credits : Data flit is ready for transmission but could not be sent", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Data Flit Not Sent : TSV High", + "EventCode": "0x55", + "EventName": "UNC_M3UPI_RxC_DATA_FLITS_NOT_SENT.TSV_HI", + "PerPkg": "1", + "PublicDescription": "Data Flit Not Sent : TSV High : Data flit is ready for transmission but could not be sent : data flit is ready for transmission but was not sent while tsv high", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Data Flit Not Sent : Cycle valid for Flit", + "EventCode": "0x55", + "EventName": "UNC_M3UPI_RxC_DATA_FLITS_NOT_SENT.VALID_FOR_FLIT", + "PerPkg": "1", + "PublicDescription": "Data Flit Not Sent : Cycle valid for Flit : Data flit is ready for transmission but could not be sent : data flit is ready for transmission but was not sent while cycle is valid for flit transmission", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence : Wait on Pump 0", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P0_WAIT", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : Wait on Pump 0 : generating bl data flit sequence; waiting for data pump 0", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P1P_AT_LIMIT", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : pump-1-pending logic is at capacity (pending table plus completion fifo at limit)", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P1P_BUSY", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : pump-1-pending logic is tracking at least one message", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P1P_FIFO_FULL", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : pump-1-pending completion fifo is full", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P1P_HOLD_P0", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : pump-1-pending logic is at or near capacity, such that pump-0-only bl messages are getting stalled in slotting stage", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P1P_TO_LIMBO", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : a bl message finished but is in limbo and moved to pump-1-pending logic", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Generating BL Data Flit Sequence : Wait on Pump 1", + "EventCode": "0x57", + "EventName": "UNC_M3UPI_RxC_FLITS_GEN_BL.P1_WAIT", + "PerPkg": "1", + "PublicDescription": "Generating BL Data Flit Sequence : Wait on Pump 1 : generating bl data flit sequence; waiting for data pump 1", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_IN_HOLDOFF", + "EventCode": "0x58", + "EventName": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_IN_HOLDOFF", + "PerPkg": "1", + "PublicDescription": ": slot 2 request naturally serviced during hold-off period", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_IN_SERVICE", + "EventCode": "0x58", + "EventName": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_IN_SERVICE", + "PerPkg": "1", + "PublicDescription": ": slot 2 request forcibly serviced during service window", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_RECEIVED", + "EventCode": "0x58", + "EventName": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_RECEIVED", + "PerPkg": "1", + "PublicDescription": ": slot 2 request received from link layer while idle (with no slot 2 request active immediately prior)", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_WITHDRAWN", + "EventCode": "0x58", + "EventName": "UNC_M3UPI_RxC_FLITS_MISC.S2REQ_WITHDRAWN", + "PerPkg": "1", + "PublicDescription": ": slot 2 request withdrawn during hold-off period or service window", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : All", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.ALL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : Needs Data Flit", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.NEED_DATA", + "PerPkg": "1", + "PublicDescription": "Slotting BL Message Into Header Flit : Needs Data Flit : BL message requires data flit sequence", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : Wait on Pump 0", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.P0_WAIT", + "PerPkg": "1", + "PublicDescription": "Slotting BL Message Into Header Flit : Wait on Pump 0 : Waiting for header pump 0", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : Don't Need Pump 1", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.P1_NOT_REQ", + "PerPkg": "1", + "PublicDescription": "Slotting BL Message Into Header Flit : Don't Need Pump 1 : Header pump 1 is not required for flit", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : Don't Need Pump 1 - Bubble", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.P1_NOT_REQ_BUT_BUBBLE", + "PerPkg": "1", + "PublicDescription": "Slotting BL Message Into Header Flit : Don't Need Pump 1 - Bubble : Header pump 1 is not required for flit but flit transmission delayed", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : Don't Need Pump 1 - Not Avail", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.P1_NOT_REQ_NOT_AVAIL", + "PerPkg": "1", + "PublicDescription": "Slotting BL Message Into Header Flit : Don't Need Pump 1 - Not Avail : Header pump 1 is not required for flit and not available", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Slotting BL Message Into Header Flit : Wait on Pump 1", + "EventCode": "0x56", + "EventName": "UNC_M3UPI_RxC_FLITS_SLOT_BL.P1_WAIT", + "PerPkg": "1", + "PublicDescription": "Slotting BL Message Into Header Flit : Wait on Pump 1 : Waiting for header pump 1", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1 : Accumulate", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.ACCUM", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Accumulate : Events related to Header Flit Generation - Set 1 : Header flit slotting control state machine is in any accumulate state; multi-message flit may be assembled over multiple cycles", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1 : Accumulate Ready", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.ACCUM_READ", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Accumulate Ready : Events related to Header Flit Generation - Set 1 : header flit slotting control state machine is in accum_ready state; flit is ready to send but transmission is blocked; more messages may be slotted into flit", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1 : Accumulate Wasted", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.ACCUM_WASTED", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Accumulate Wasted : Events related to Header Flit Generation - Set 1 : Flit is being assembled over multiple cycles, but no additional message is being slotted into flit in current cycle; accumulate cycle is wasted", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1 : Run-Ahead - Blocked", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.AHEAD_BLOCKED", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Run-Ahead - Blocked : Events related to Header Flit Generation - Set 1 : Header flit slotting entered run-ahead state; new header flit is started while transmission of prior, fully assembled flit is blocked", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.AHEAD_MSG1_AFTER", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Events related to Header Flit Generation - Set 1 : run-ahead mode: message was slotted only after run-ahead was over; run-ahead mode definitely wasted", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1 : Run-Ahead - Message", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.AHEAD_MSG1_DURING", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Run-Ahead - Message : Events related to Header Flit Generation - Set 1 : run-ahead mode: one message slotted during run-ahead", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.AHEAD_MSG2_AFTER", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Events related to Header Flit Generation - Set 1 : run-ahead mode: second message slotted immediately after run-ahead; potential run-ahead success", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 1", + "EventCode": "0x51", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR1.AHEAD_MSG2_SENT", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 1 : Events related to Header Flit Generation - Set 1 : run-ahead mode: two (or three) message flit sent immediately after run-ahead; complete run-ahead success", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 2 : Parallel Ok", + "EventCode": "0x52", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR2.PAR", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 2 : Parallel Ok : Events related to Header Flit Generation - Set 2 : new header flit construction may proceed in parallel with data flit sequence", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 2 : Parallel Flit Finished", + "EventCode": "0x52", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR2.PAR_FLIT", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 2 : Parallel Flit Finished : Events related to Header Flit Generation - Set 2 : header flit finished assembly in parallel with data flit sequence", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 2 : Parallel Message", + "EventCode": "0x52", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR2.PAR_MSG", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 2 : Parallel Message : Events related to Header Flit Generation - Set 2 : message is slotted into header flit in parallel with data flit sequence", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 2 : Rate-matching Stall", + "EventCode": "0x52", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR2.RMSTALL", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 2 : Rate-matching Stall : Events related to Header Flit Generation - Set 2 : Rate-matching stall injected", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Flit Gen - Header 2 : Rate-matching Stall - No Message", + "EventCode": "0x52", + "EventName": "UNC_M3UPI_RxC_FLIT_GEN_HDR2.RMSTALL_NOMSG", + "PerPkg": "1", + "PublicDescription": "Flit Gen - Header 2 : Rate-matching Stall - No Message : Events related to Header Flit Generation - Set 2 : Rate matching stall injected, but no additional message slotted during stall cycle", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : One Message", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.1_MSG", + "PerPkg": "1", + "PublicDescription": "Sent Header Flit : One Message : One message in flit; VNA or non-VNA flit", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : One Message in non-VNA", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.1_MSG_VNX", + "PerPkg": "1", + "PublicDescription": "Sent Header Flit : One Message in non-VNA : One message in flit; non-VNA flit", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : Two Messages", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.2_MSGS", + "PerPkg": "1", + "PublicDescription": "Sent Header Flit : Two Messages : Two messages in flit; VNA flit", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : Three Messages", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.3_MSGS", + "PerPkg": "1", + "PublicDescription": "Sent Header Flit : Three Messages : Three messages in flit; VNA flit", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : One Slot Taken", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.SLOTS_1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : Two Slots Taken", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.SLOTS_2", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Sent Header Flit : All Slots Taken", + "EventCode": "0x54", + "EventName": "UNC_M3UPI_RxC_HDR_FLITS_SENT.SLOTS_3", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : All", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.ALL", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : All : header flit is ready for transmission but could not be sent : header flit is ready for transmission but could not be sent for any reason, e.g. no credits, low tsv, stall injection", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : No BGF Credits", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.NO_BGF_CRD", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : No BGF Credits : header flit is ready for transmission but could not be sent : No BGF credits available", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : No BGF Credits + No Extra Message Slotted", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.NO_BGF_NO_MSG", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : No BGF Credits + No Extra Message Slotted : header flit is ready for transmission but could not be sent : No BGF credits available; no additional message slotted into flit", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : No TxQ Credits", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.NO_TXQ_CRD", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : No TxQ Credits : header flit is ready for transmission but could not be sent : No TxQ credits available", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : No TxQ Credits + No Extra Message Slotted", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.NO_TXQ_NO_MSG", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : No TxQ Credits + No Extra Message Slotted : header flit is ready for transmission but could not be sent : No TxQ credits available; no additional message slotted into flit", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : TSV High", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.TSV_HI", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : TSV High : header flit is ready for transmission but could not be sent : header flit is ready for transmission but was not sent while tsv high", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Header Not Sent : Cycle valid for Flit", + "EventCode": "0x53", + "EventName": "UNC_M3UPI_RxC_HDR_FLIT_NOT_SENT.VALID_FOR_FLIT", + "PerPkg": "1", + "PublicDescription": "Header Not Sent : Cycle valid for Flit : header flit is ready for transmission but could not be sent : header flit is ready for transmission but was not sent while cycle is valid for flit transmission", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Message Held : Can't Slot AD", + "EventCode": "0x50", + "EventName": "UNC_M3UPI_RxC_HELD.CANT_SLOT_AD", + "PerPkg": "1", + "PublicDescription": "Message Held : Can't Slot AD : some AD message could not be slotted (logical OR of all AD events under INGR_SLOT_CANT_MC_VN{0,1})", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Message Held : Can't Slot BL", + "EventCode": "0x50", + "EventName": "UNC_M3UPI_RxC_HELD.CANT_SLOT_BL", + "PerPkg": "1", + "PublicDescription": "Message Held : Can't Slot BL : some BL message could not be slotted (logical OR of all BL events under INGR_SLOT_CANT_MC_VN{0,1})", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Message Held : Parallel Attempt", + "EventCode": "0x50", + "EventName": "UNC_M3UPI_RxC_HELD.PARALLEL_ATTEMPT", + "PerPkg": "1", + "PublicDescription": "Message Held : Parallel Attempt : ad and bl messages attempted to slot into the same flit in parallel", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Message Held : Parallel Success", + "EventCode": "0x50", + "EventName": "UNC_M3UPI_RxC_HELD.PARALLEL_SUCCESS", + "PerPkg": "1", + "PublicDescription": "Message Held : Parallel Success : ad and bl messages were actually slotted into the same flit in parallel", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Message Held : VN0", + "EventCode": "0x50", + "EventName": "UNC_M3UPI_RxC_HELD.VN0", + "PerPkg": "1", + "PublicDescription": "Message Held : VN0 : vn0 message(s) that couldn't be slotted into last vn0 flit are held in slotting stage while processing vn1 flit", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Message Held : VN1", + "EventCode": "0x50", + "EventName": "UNC_M3UPI_RxC_HELD.VN1", + "PerPkg": "1", + "PublicDescription": "Message Held : VN1 : vn1 message(s) that couldn't be slotted into last vn1 flit are held in slotting stage while processing vn0 flit", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : REQ on AD", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.AD_REQ", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : REQ on AD : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : RSP on AD", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.AD_RSP", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : RSP on AD : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : SNP on AD", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.AD_SNP", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : SNP on AD : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : NCB on BL", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.BL_NCB", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : NCB on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : NCS on BL", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.BL_NCS", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : NCS on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : RSP on BL", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.BL_RSP", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : RSP on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 message can't slot into flit : WB on BL", + "EventCode": "0x4e", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN0.BL_WB", + "PerPkg": "1", + "PublicDescription": "VN0 message can't slot into flit : WB on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : REQ on AD", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.AD_REQ", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : REQ on AD : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : RSP on AD", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.AD_RSP", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : RSP on AD : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : SNP on AD", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.AD_SNP", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : SNP on AD : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : NCB on BL", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.BL_NCB", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : NCB on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : NCS on BL", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.BL_NCS", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : NCS on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Non-Coherent Standard (NCS) messages on BL.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : RSP on BL", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.BL_RSP", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : RSP on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 message can't slot into flit : WB on BL", + "EventCode": "0x4f", + "EventName": "UNC_M3UPI_RxC_PACKING_MISS_VN1.BL_WB", + "PerPkg": "1", + "PublicDescription": "VN1 message can't slot into flit : WB on BL : Count cases where Ingress has packets to send but did not have time to pack into flit before sending to Agent so slot was left NULL which could have been used. : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Remote VNA Credits : Any In Use", + "EventCode": "0x5a", + "EventName": "UNC_M3UPI_RxC_VNA_CRD.ANY_IN_USE", + "PerPkg": "1", + "PublicDescription": "Remote VNA Credits : Any In Use : At least one remote vna credit is in use", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Remote VNA Credits : Corrected", + "EventCode": "0x5a", + "EventName": "UNC_M3UPI_RxC_VNA_CRD.CORRECTED", + "PerPkg": "1", + "PublicDescription": "Remote VNA Credits : Corrected : Number of remote vna credits corrected (local return) per cycle", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Remote VNA Credits : Level < 1", + "EventCode": "0x5a", + "EventName": "UNC_M3UPI_RxC_VNA_CRD.LT1", + "PerPkg": "1", + "PublicDescription": "Remote VNA Credits : Level < 1 : Remote vna credit level is less than 1 (i.e. no vna credits available)", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Remote VNA Credits : Level < 10", + "EventCode": "0x5a", + "EventName": "UNC_M3UPI_RxC_VNA_CRD.LT10", + "PerPkg": "1", + "PublicDescription": "Remote VNA Credits : Level < 10 : remote vna credit level is less than 10; parallel vn0/vn1 arb not possible", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Remote VNA Credits : Level < 4", + "EventCode": "0x5a", + "EventName": "UNC_M3UPI_RxC_VNA_CRD.LT4", + "PerPkg": "1", + "PublicDescription": "Remote VNA Credits : Level < 4 : Remote vna credit level is less than 4; bl (or ad requiring 4 vna) cannot arb on vna", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Remote VNA Credits : Level < 5", + "EventCode": "0x5a", + "EventName": "UNC_M3UPI_RxC_VNA_CRD.LT5", + "PerPkg": "1", + "PublicDescription": "Remote VNA Credits : Level < 5 : Remote vna credit level is less than 5; parallel ad/bl arb on vna not possible", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.REQ_ADBL_ALLOC_L5", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.REQ_ADBL_ALLOC_L5", + "PerPkg": "1", + "PublicDescription": ": remote vna credit count was less than 5 and allocation to ad or bl messages was required", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.REQ_VN01_ALLOC_LT10", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.REQ_VN01_ALLOC_LT10", + "PerPkg": "1", + "PublicDescription": ": remote vna credit count was less than 10 and allocation to vn0 or vn1 was required", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN0_JUST_AD", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN0_JUST_AD", + "PerPkg": "1", + "PublicDescription": ": on vn0, remote vna credits were allocated only to ad messages, not to bl", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN0_JUST_BL", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN0_JUST_BL", + "PerPkg": "1", + "PublicDescription": ": on vn0, remote vna credits were allocated only to bl messages, not to ad", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN0_ONLY", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN0_ONLY", + "PerPkg": "1", + "PublicDescription": ": remote vna credits were allocated only to vn0, not to vn1", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN1_JUST_AD", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN1_JUST_AD", + "PerPkg": "1", + "PublicDescription": ": on vn1, remote vna credits were allocated only to ad messages, not to bl", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN1_JUST_BL", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN1_JUST_BL", + "PerPkg": "1", + "PublicDescription": ": on vn1, remote vna credits were allocated only to bl messages, not to ad", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN1_ONLY", + "EventCode": "0x59", + "EventName": "UNC_M3UPI_RxC_VNA_CRD_MISC.VN1_ONLY", + "PerPkg": "1", + "PublicDescription": ": remote vna credits were allocated only to vn1, not to vn0", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN0 REQ Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN0_REQ", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN0 REQ Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN0 RSP Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN0 RSP Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN0 SNP Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN0_SNP", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN0 SNP Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN0 WB Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN0_WB", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN0 WB Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN1 REQ Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN1_REQ", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN1 REQ Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN1 RSP Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN1 RSP Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN1 SNP Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN1_SNP", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN1 SNP Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for AD : VN1 WB Messages", + "EventCode": "0x30", + "EventName": "UNC_M3UPI_TxC_AD_ARB_FAIL.VN1_WB", + "PerPkg": "1", + "PublicDescription": "Failed ARB for AD : VN1 WB Messages : AD arb but no win; arb request asserted but not won", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD FlowQ Bypass", + "EventCode": "0x2C", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_BYPASS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts cases when the AD flowQ is bypassed (S0, S1 and S2 indicate which slot was bypassed with S0 having the highest priority and S2 the least)", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD FlowQ Bypass", + "EventCode": "0x2c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_BYPASS.AD_SLOT0", + "PerPkg": "1", + "PublicDescription": "AD FlowQ Bypass : Counts cases when the AD flowQ is bypassed (S0, S1 and S2 indicate which slot was bypassed with S0 having the highest priority and S2 the least)", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD FlowQ Bypass", + "EventCode": "0x2c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_BYPASS.AD_SLOT1", + "PerPkg": "1", + "PublicDescription": "AD FlowQ Bypass : Counts cases when the AD flowQ is bypassed (S0, S1 and S2 indicate which slot was bypassed with S0 having the highest priority and S2 the least)", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD FlowQ Bypass", + "EventCode": "0x2c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_BYPASS.AD_SLOT2", + "PerPkg": "1", + "PublicDescription": "AD FlowQ Bypass : Counts cases when the AD flowQ is bypassed (S0, S1 and S2 indicate which slot was bypassed with S0 having the highest priority and S2 the least)", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD FlowQ Bypass", + "EventCode": "0x2c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_BYPASS.BL_EARLY_RSP", + "PerPkg": "1", + "PublicDescription": "AD FlowQ Bypass : Counts cases when the AD flowQ is bypassed (S0, S1 and S2 indicate which slot was bypassed with S0 having the highest priority and S2 the least)", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN0 REQ Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN0_REQ", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN0 REQ Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN0 RSP Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN0 RSP Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN0 SNP Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN0_SNP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN0 SNP Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN0 WB Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN0_WB", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN0 WB Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN1 REQ Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN1_REQ", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN1 REQ Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN1 RSP Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN1 RSP Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN1 SNP Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN1_SNP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN1 SNP Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Not Empty : VN1 WB Messages", + "EventCode": "0x27", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_CYCLES_NE.VN1_WB", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Not Empty : VN1 WB Messages : Number of cycles the AD Egress queue is Not Empty", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN0 REQ Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN0_REQ", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN0 REQ Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN0 RSP Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN0 RSP Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN0 SNP Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN0_SNP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN0 SNP Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN0 WB Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN0_WB", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN0 WB Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN1 REQ Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN1_REQ", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN1 REQ Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN1 RSP Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN1 RSP Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Inserts : VN1 SNP Messages", + "EventCode": "0x2d", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_INSERTS.VN1_SNP", + "PerPkg": "1", + "PublicDescription": "AD Flow Q Inserts : VN1 SNP Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN0 REQ Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN0_REQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN0 RSP Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN0_RSP", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN0 SNP Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN0_SNP", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN0 WB Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN0_WB", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN1 REQ Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN1_REQ", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN1 RSP Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN1_RSP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AD Flow Q Occupancy : VN1 SNP Messages", + "EventCode": "0x1c", + "EventName": "UNC_M3UPI_TxC_AD_FLQ_OCCUPANCY.VN1_SNP", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AK Flow Q Inserts", + "EventCode": "0x2f", + "EventName": "UNC_M3UPI_TxC_AK_FLQ_INSERTS", + "PerPkg": "1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "AK Flow Q Occupancy", + "EventCode": "0x1e", + "EventName": "UNC_M3UPI_TxC_AK_FLQ_OCCUPANCY", + "PerPkg": "1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN0 NCB Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN0_NCB", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN0 NCB Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN0 NCS Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN0_NCS", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN0 NCS Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN0 RSP Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN0 RSP Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN0 WB Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN0_WB", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN0 WB Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN1 NCS Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN1_NCB", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN1 NCS Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN1 NCB Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN1_NCS", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN1 NCB Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN1 RSP Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN1 RSP Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Failed ARB for BL : VN1 WB Messages", + "EventCode": "0x35", + "EventName": "UNC_M3UPI_TxC_BL_ARB_FAIL.VN1_WB", + "PerPkg": "1", + "PublicDescription": "Failed ARB for BL : VN1 WB Messages : BL arb but no win; arb request asserted but not won", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN0 REQ Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN0_REQ", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN0 REQ Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN0 RSP Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN0 RSP Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN0 SNP Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN0_SNP", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN0 SNP Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN0 WB Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN0_WB", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN0 WB Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN1 REQ Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN1_REQ", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN1 REQ Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN1 RSP Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN1 RSP Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN1 SNP Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN1_SNP", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN1 SNP Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Not Empty : VN1 WB Messages", + "EventCode": "0x28", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_CYCLES_NE.VN1_WB", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Not Empty : VN1 WB Messages : Number of cycles the BL Egress queue is Not Empty", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN0 RSP Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN0_NCB", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN0 RSP Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN0 WB Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN0_NCS", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN0 WB Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN0 NCS Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN0 NCS Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN0 NCB Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN0_WB", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN0 NCB Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN1 RSP Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN1_NCB", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN1 RSP Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN1 WB Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN1_NCS", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN1 WB Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN1_NCB Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN1_NCB Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Inserts : VN1_NCS Messages", + "EventCode": "0x2e", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_INSERTS.VN1_WB", + "PerPkg": "1", + "PublicDescription": "BL Flow Q Inserts : VN1_NCS Messages : Counts the number of allocations into the QPI FlowQ. This can be used in conjunction with the QPI FlowQ Occupancy Accumulator event in order to calculate average queue latency. Only a single FlowQ queue can be tracked at any given time. It is not possible to filter based on direction or polarity.", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 NCB Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN0_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 NCS Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN0_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 RSP Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN0_RSP", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 WB Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN0_WB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1_NCS Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN1_NCB", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1_NCB Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN1_NCS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1 RSP Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN1_RSP", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1 WB Messages", + "EventCode": "0x1d", + "EventName": "UNC_M3UPI_TxC_BL_FLQ_OCCUPANCY.VN1_WB", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 RSP Messages", + "EventCode": "0x1f", + "EventName": "UNC_M3UPI_TxC_BL_WB_FLQ_OCCUPANCY.VN0_LOCAL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 WB Messages", + "EventCode": "0x1f", + "EventName": "UNC_M3UPI_TxC_BL_WB_FLQ_OCCUPANCY.VN0_THROUGH", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN0 NCB Messages", + "EventCode": "0x1f", + "EventName": "UNC_M3UPI_TxC_BL_WB_FLQ_OCCUPANCY.VN0_WRPULL", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1 RSP Messages", + "EventCode": "0x1f", + "EventName": "UNC_M3UPI_TxC_BL_WB_FLQ_OCCUPANCY.VN1_LOCAL", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1 WB Messages", + "EventCode": "0x1f", + "EventName": "UNC_M3UPI_TxC_BL_WB_FLQ_OCCUPANCY.VN1_THROUGH", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "BL Flow Q Occupancy : VN1_NCS Messages", + "EventCode": "0x1f", + "EventName": "UNC_M3UPI_TxC_BL_WB_FLQ_OCCUPANCY.VN1_WRPULL", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VN0 REQ Messages", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VN0_REQ", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VN0 REQ Messages : No credits available to send to UPIs on the AD Ring", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VN0 RSP Messages", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VN0 RSP Messages : No credits available to send to UPIs on the AD Ring", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VN0 SNP Messages", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VN0_SNP", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VN0 SNP Messages : No credits available to send to UPIs on the AD Ring", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VN1 REQ Messages", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VN1_REQ", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VN1 REQ Messages : No credits available to send to UPIs on the AD Ring", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VN1 RSP Messages", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VN1 RSP Messages : No credits available to send to UPIs on the AD Ring", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VN1 SNP Messages", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VN1_SNP", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VN1 SNP Messages : No credits available to send to UPIs on the AD Ring", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 AD Credits Empty : VNA", + "EventCode": "0x20", + "EventName": "UNC_M3UPI_UPI_PEER_AD_CREDITS_EMPTY.VNA", + "PerPkg": "1", + "PublicDescription": "UPI0 AD Credits Empty : VNA : No credits available to send to UPIs on the AD Ring", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VN0 RSP Messages", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VN0_NCS_NCB", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VN0 RSP Messages : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VN0 REQ Messages", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VN0_RSP", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VN0 REQ Messages : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VN0 SNP Messages", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VN0_WB", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VN0 SNP Messages : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VN1 RSP Messages", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VN1_NCS_NCB", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VN1 RSP Messages : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VN1 REQ Messages", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VN1_RSP", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VN1 REQ Messages : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VN1 SNP Messages", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VN1_WB", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VN1 SNP Messages : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UPI0 BL Credits Empty : VNA", + "EventCode": "0x21", + "EventName": "UNC_M3UPI_UPI_PEER_BL_CREDITS_EMPTY.VNA", + "PerPkg": "1", + "PublicDescription": "UPI0 BL Credits Empty : VNA : No credits available to send to UPI on the BL Ring (diff between non-SMI and SMI mode)", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "FlowQ Generated Prefetch", + "EventCode": "0x29", + "EventName": "UNC_M3UPI_UPI_PREFETCH_SPAWN", + "PerPkg": "1", + "PublicDescription": "FlowQ Generated Prefetch : Count cases where FlowQ causes spawn of Prefetch to iMC/SMI3 target", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Credit Used : WB on BL", + "EventCode": "0x5b", + "EventName": "UNC_M3UPI_VN0_CREDITS_USED.NCB", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Used : WB on BL : Number of times a VN0 credit was used on the DRS message channel. In order for a request to be transferred across UPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN0. VNA is a shared pool used to achieve high performance. The VN0 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail. This counts the number of times a VN0 credit was used. Note that a single VN0 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN0 will only count a single credit even though it may use multiple buffers. : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Credit Used : NCB on BL", + "EventCode": "0x5b", + "EventName": "UNC_M3UPI_VN0_CREDITS_USED.NCS", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Used : NCB on BL : Number of times a VN0 credit was used on the DRS message channel. In order for a request to be transferred across UPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN0. VNA is a shared pool used to achieve high performance. The VN0 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail. This counts the number of times a VN0 credit was used. Note that a single VN0 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN0 will only count a single credit even though it may use multiple buffers. : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Credit Used : REQ on AD", + "EventCode": "0x5b", + "EventName": "UNC_M3UPI_VN0_CREDITS_USED.REQ", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Used : REQ on AD : Number of times a VN0 credit was used on the DRS message channel. In order for a request to be transferred across UPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN0. VNA is a shared pool used to achieve high performance. The VN0 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail. This counts the number of times a VN0 credit was used. Note that a single VN0 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN0 will only count a single credit even though it may use multiple buffers. : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Credit Used : RSP on AD", + "EventCode": "0x5b", + "EventName": "UNC_M3UPI_VN0_CREDITS_USED.RSP", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Used : RSP on AD : Number of times a VN0 credit was used on the DRS message channel. In order for a request to be transferred across UPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN0. VNA is a shared pool used to achieve high performance. The VN0 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail. This counts the number of times a VN0 credit was used. Note that a single VN0 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN0 will only count a single credit even though it may use multiple buffers. : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Credit Used : SNP on AD", + "EventCode": "0x5b", + "EventName": "UNC_M3UPI_VN0_CREDITS_USED.SNP", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Used : SNP on AD : Number of times a VN0 credit was used on the DRS message channel. In order for a request to be transferred across UPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN0. VNA is a shared pool used to achieve high performance. The VN0 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail. This counts the number of times a VN0 credit was used. Note that a single VN0 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN0 will only count a single credit even though it may use multiple buffers. : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 Credit Used : RSP on BL", + "EventCode": "0x5b", + "EventName": "UNC_M3UPI_VN0_CREDITS_USED.WB", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Used : RSP on BL : Number of times a VN0 credit was used on the DRS message channel. In order for a request to be transferred across UPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN0. VNA is a shared pool used to achieve high performance. The VN0 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN0 if they fail. This counts the number of times a VN0 credit was used. Note that a single VN0 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN0 will only count a single credit even though it may use multiple buffers. : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 No Credits : WB on BL", + "EventCode": "0x5d", + "EventName": "UNC_M3UPI_VN0_NO_CREDITS.NCB", + "PerPkg": "1", + "PublicDescription": "VN0 No Credits : WB on BL : Number of Cycles there were no VN0 Credits : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 No Credits : NCB on BL", + "EventCode": "0x5d", + "EventName": "UNC_M3UPI_VN0_NO_CREDITS.NCS", + "PerPkg": "1", + "PublicDescription": "VN0 No Credits : NCB on BL : Number of Cycles there were no VN0 Credits : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 No Credits : REQ on AD", + "EventCode": "0x5d", + "EventName": "UNC_M3UPI_VN0_NO_CREDITS.REQ", + "PerPkg": "1", + "PublicDescription": "VN0 No Credits : REQ on AD : Number of Cycles there were no VN0 Credits : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 No Credits : RSP on AD", + "EventCode": "0x5d", + "EventName": "UNC_M3UPI_VN0_NO_CREDITS.RSP", + "PerPkg": "1", + "PublicDescription": "VN0 No Credits : RSP on AD : Number of Cycles there were no VN0 Credits : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 No Credits : SNP on AD", + "EventCode": "0x5d", + "EventName": "UNC_M3UPI_VN0_NO_CREDITS.SNP", + "PerPkg": "1", + "PublicDescription": "VN0 No Credits : SNP on AD : Number of Cycles there were no VN0 Credits : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN0 No Credits : RSP on BL", + "EventCode": "0x5d", + "EventName": "UNC_M3UPI_VN0_NO_CREDITS.WB", + "PerPkg": "1", + "PublicDescription": "VN0 No Credits : RSP on BL : Number of Cycles there were no VN0 Credits : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 Credit Used : WB on BL", + "EventCode": "0x5c", + "EventName": "UNC_M3UPI_VN1_CREDITS_USED.NCB", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Used : WB on BL : Number of times a VN1 credit was used on the WB message channel. In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN1. VNA is a shared pool used to achieve high performance. The VN1 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail. This counts the number of times a VN1 credit was used. Note that a single VN1 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN1 will only count a single credit even though it may use multiple buffers. : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 Credit Used : NCB on BL", + "EventCode": "0x5c", + "EventName": "UNC_M3UPI_VN1_CREDITS_USED.NCS", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Used : NCB on BL : Number of times a VN1 credit was used on the WB message channel. In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN1. VNA is a shared pool used to achieve high performance. The VN1 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail. This counts the number of times a VN1 credit was used. Note that a single VN1 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN1 will only count a single credit even though it may use multiple buffers. : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 Credit Used : REQ on AD", + "EventCode": "0x5c", + "EventName": "UNC_M3UPI_VN1_CREDITS_USED.REQ", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Used : REQ on AD : Number of times a VN1 credit was used on the WB message channel. In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN1. VNA is a shared pool used to achieve high performance. The VN1 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail. This counts the number of times a VN1 credit was used. Note that a single VN1 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN1 will only count a single credit even though it may use multiple buffers. : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 Credit Used : RSP on AD", + "EventCode": "0x5c", + "EventName": "UNC_M3UPI_VN1_CREDITS_USED.RSP", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Used : RSP on AD : Number of times a VN1 credit was used on the WB message channel. In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN1. VNA is a shared pool used to achieve high performance. The VN1 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail. This counts the number of times a VN1 credit was used. Note that a single VN1 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN1 will only count a single credit even though it may use multiple buffers. : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 Credit Used : SNP on AD", + "EventCode": "0x5c", + "EventName": "UNC_M3UPI_VN1_CREDITS_USED.SNP", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Used : SNP on AD : Number of times a VN1 credit was used on the WB message channel. In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN1. VNA is a shared pool used to achieve high performance. The VN1 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail. This counts the number of times a VN1 credit was used. Note that a single VN1 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN1 will only count a single credit even though it may use multiple buffers. : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 Credit Used : RSP on BL", + "EventCode": "0x5c", + "EventName": "UNC_M3UPI_VN1_CREDITS_USED.WB", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Used : RSP on BL : Number of times a VN1 credit was used on the WB message channel. In order for a request to be transferred across QPI, it must be guaranteed to have a flit buffer on the remote socket to sink into. There are two credit pools, VNA and VN1. VNA is a shared pool used to achieve high performance. The VN1 pool has reserved entries for each message class and is used to prevent deadlock. Requests first attempt to acquire a VNA credit, and then fall back to VN1 if they fail. This counts the number of times a VN1 credit was used. Note that a single VN1 credit holds access to potentially multiple flit buffers. For example, a transfer that uses VNA could use 9 flit buffers and in that case uses 9 credits. A transfer on VN1 will only count a single credit even though it may use multiple buffers. : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 No Credits : WB on BL", + "EventCode": "0x5e", + "EventName": "UNC_M3UPI_VN1_NO_CREDITS.NCB", + "PerPkg": "1", + "PublicDescription": "VN1 No Credits : WB on BL : Number of Cycles there were no VN1 Credits : Data Response (WB) messages on BL. WB is generally used to transmit data with coherency. For example, remote reads and writes, or cache to cache transfers will transmit their data using WB.", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 No Credits : NCB on BL", + "EventCode": "0x5e", + "EventName": "UNC_M3UPI_VN1_NO_CREDITS.NCS", + "PerPkg": "1", + "PublicDescription": "VN1 No Credits : NCB on BL : Number of Cycles there were no VN1 Credits : Non-Coherent Broadcast (NCB) messages on BL. NCB is generally used to transmit data without coherency. For example, non-coherent read data returns.", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 No Credits : REQ on AD", + "EventCode": "0x5e", + "EventName": "UNC_M3UPI_VN1_NO_CREDITS.REQ", + "PerPkg": "1", + "PublicDescription": "VN1 No Credits : REQ on AD : Number of Cycles there were no VN1 Credits : Home (REQ) messages on AD. REQ is generally used to send requests, request responses, and snoop responses.", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 No Credits : RSP on AD", + "EventCode": "0x5e", + "EventName": "UNC_M3UPI_VN1_NO_CREDITS.RSP", + "PerPkg": "1", + "PublicDescription": "VN1 No Credits : RSP on AD : Number of Cycles there were no VN1 Credits : Response (RSP) messages on AD. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 No Credits : SNP on AD", + "EventCode": "0x5e", + "EventName": "UNC_M3UPI_VN1_NO_CREDITS.SNP", + "PerPkg": "1", + "PublicDescription": "VN1 No Credits : SNP on AD : Number of Cycles there were no VN1 Credits : Snoops (SNP) messages on AD. SNP is used for outgoing snoops.", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "VN1 No Credits : RSP on BL", + "EventCode": "0x5e", + "EventName": "UNC_M3UPI_VN1_NO_CREDITS.WB", + "PerPkg": "1", + "PublicDescription": "VN1 No Credits : RSP on BL : Number of Cycles there were no VN1 Credits : Response (RSP) messages on BL. RSP packets are used to transmit a variety of protocol flits including grants and completions (CMP).", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_EQ_LOCALDEST_VN0", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_EQ_LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x82", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_EQ_LOCALDEST_VN1", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_EQ_LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0xa0", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_GT_LOCALDEST_VN0", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_GT_LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x81", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_GT_LOCALDEST_VN1", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_GT_LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0x90", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_LT_LOCALDEST_VN0", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_LT_LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x84", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_LT_LOCALDEST_VN1", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.BOTHNONZERO_RT_LT_LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0xc0", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.RT_EQ_LOCALDEST_VN0", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.RT_EQ_LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.RT_EQ_LOCALDEST_VN1", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.RT_EQ_LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.RT_GT_LOCALDEST_VN0", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.RT_GT_LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.RT_GT_LOCALDEST_VN1", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.RT_GT_LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.RT_LT_LOCALDEST_VN0", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.RT_LT_LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_OCC_COMPARE.RT_LT_LOCALDEST_VN1", + "EventCode": "0x7e", + "EventName": "UNC_M3UPI_WB_OCC_COMPARE.RT_LT_LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.LOCALDEST_VN0", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.LOCALDEST_VN0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.LOCALDEST_VN1", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.LOCALDEST_VN1", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.LOCAL_AND_RT_VN0", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.LOCAL_AND_RT_VN0", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.LOCAL_AND_RT_VN1", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.LOCAL_AND_RT_VN1", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.ROUTETHRU_VN0", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.ROUTETHRU_VN0", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.ROUTETHRU_VN1", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.ROUTETHRU_VN1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.WAITING4PULL_VN0", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.WAITING4PULL_VN0", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_WB_PENDING.WAITING4PULL_VN1", + "EventCode": "0x7d", + "EventName": "UNC_M3UPI_WB_PENDING.WAITING4PULL_VN1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.ARB", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.ARB", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message is making arbitration request", + "UMask": "0x4", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.ARRIVED", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.ARRIVED", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message arrived in ingress pipeline", + "UMask": "0x1", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.BYPASS", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.BYPASS", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message took bypass path", + "UMask": "0x2", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.FLITTED", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.FLITTED", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message was slotted into flit (non bypass)", + "UMask": "0x10", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.LOST_ARB", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.LOST_ARB", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message lost arbitration", + "UMask": "0x8", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.LOST_OLD", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.LOST_OLD", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message was dropped because it became too old", + "UMask": "0x20", + "Unit": "M3UPI" + }, + { + "BriefDescription": "UNC_M3UPI_XPT_PFTCH.LOST_QFULL", + "EventCode": "0x61", + "EventName": "UNC_M3UPI_XPT_PFTCH.LOST_QFULL", + "PerPkg": "1", + "PublicDescription": ": xpt prefetch message was dropped because it was overwritten by new message while prefetch queue was full", + "UMask": "0x40", + "Unit": "M3UPI" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (AD Bouncable)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.AD_BNC", + "PerPkg": "1", + "PublicDescription": "AD Bouncable : Number of allocations into the CRS Egress", + "UMask": "0x1", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (AD credited)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.AD_CRD", + "PerPkg": "1", + "PublicDescription": "AD credited : Number of allocations into the CRS Egress", + "UMask": "0x2", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (AK)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.AK", + "PerPkg": "1", + "PublicDescription": "AK : Number of allocations into the CRS Egress", + "UMask": "0x10", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (AKC)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.AKC", + "PerPkg": "1", + "PublicDescription": "AKC : Number of allocations into the CRS Egress", + "UMask": "0x40", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (BL Bouncable)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.BL_BNC", + "PerPkg": "1", + "PublicDescription": "BL Bouncable : Number of allocations into the CRS Egress", + "UMask": "0x4", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (BL credited)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.BL_CRD", + "PerPkg": "1", + "PublicDescription": "BL credited : Number of allocations into the CRS Egress", + "UMask": "0x8", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of allocations into the CRS Egress used to queue up requests destined to the mesh (IV)", + "EventCode": "0x47", + "EventName": "UNC_MDF_CRS_TxR_INSERTS.IV", + "PerPkg": "1", + "PublicDescription": "IV : Number of allocations into the CRS Egress", + "UMask": "0x20", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of cycles incoming messages from the vertical ring that are bounced at the SBO\r\nIngress (V-EMIB) (AD)", + "EventCode": "0x4B", + "EventName": "UNC_MDF_CRS_TxR_V_BOUNCES.AD", + "PerPkg": "1", + "PublicDescription": "AD : Number of cycles incoming messages from the vertical ring that are bounced at the SBO", + "UMask": "0x1", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of cycles incoming messages from the vertical ring that are bounced at the SBO\r\nIngress (V-EMIB) (AK)", + "EventCode": "0x4B", + "EventName": "UNC_MDF_CRS_TxR_V_BOUNCES.AK", + "PerPkg": "1", + "PublicDescription": "AK : Number of cycles incoming messages from the vertical ring that are bounced at the SBO", + "UMask": "0x4", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of cycles incoming messages from the vertical ring that are bounced at the SBO\r\nIngress (V-EMIB) (AKC)", + "EventCode": "0x4B", + "EventName": "UNC_MDF_CRS_TxR_V_BOUNCES.AKC", + "PerPkg": "1", + "PublicDescription": "AKC : Number of cycles incoming messages from the vertical ring that are bounced at the SBO", + "UMask": "0x10", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of cycles incoming messages from the vertical ring that are bounced at the SBO\r\nIngress (V-EMIB) (BL)", + "EventCode": "0x4B", + "EventName": "UNC_MDF_CRS_TxR_V_BOUNCES.BL", + "PerPkg": "1", + "PublicDescription": "BL : Number of cycles incoming messages from the vertical ring that are bounced at the SBO", + "UMask": "0x2", + "Unit": "MDF" + }, + { + "BriefDescription": "Number of cycles incoming messages from the vertical ring that are bounced at the SBO\r\nIngress (V-EMIB) (IV)", + "EventCode": "0x4B", + "EventName": "UNC_MDF_CRS_TxR_V_BOUNCES.IV", + "PerPkg": "1", + "PublicDescription": "IV : Number of cycles incoming messages from the vertical ring that are bounced at the SBO", + "UMask": "0x8", + "Unit": "MDF" + }, + { + "BriefDescription": "Counts the number of cycles when the distress signals are asserted based on SBO Ingress threshold", + "EventCode": "0x15", + "EventName": "UNC_MDF_FAST_ASSERTED.AD_BNC", + "PerPkg": "1", + "PublicDescription": "AD bnc : Counts the number of cycles when the distress signals are asserted based on SBO Ingress threshold", + "UMask": "0x1", + "Unit": "MDF" + }, + { + "BriefDescription": "Counts the number of cycles when the distress signals are asserted based on SBO Ingress threshold", + "EventCode": "0x15", + "EventName": "UNC_MDF_FAST_ASSERTED.BL_CRD", + "PerPkg": "1", + "PublicDescription": "BL bnc : Counts the number of cycles when the distress signals are asserted based on SBO Ingress threshold", + "UMask": "0x2", + "Unit": "MDF" + }, + { + "BriefDescription": "UPI Clockticks", + "EventCode": "0x01", + "EventName": "UNC_UPI_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of UPI LL clock cycles while the event is enabled", + "Unit": "UPI" + }, + { + "BriefDescription": "Direct packet attempts : D2C", + "EventCode": "0x12", + "EventName": "UNC_UPI_DIRECT_ATTEMPTS.D2C", + "PerPkg": "1", + "PublicDescription": "Direct packet attempts : D2C : Counts the number of DRS packets that we attempted to do direct2core/direct2UPI on. There are 4 mutually exclusive filters. Filter [0] can be used to get successful spawns, while [1:3] provide the different failure cases. Note that this does not count packets that are not candidates for Direct2Core. The only candidates for Direct2Core are DRS packets destined for Cbos.", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "Direct packet attempts : D2K", + "EventCode": "0x12", + "EventName": "UNC_UPI_DIRECT_ATTEMPTS.D2K", + "PerPkg": "1", + "PublicDescription": "Direct packet attempts : D2K : Counts the number of DRS packets that we attempted to do direct2core/direct2UPI on. There are 4 mutually exclusive filters. Filter [0] can be used to get successful spawns, while [1:3] provide the different failure cases. Note that this does not count packets that are not candidates for Direct2Core. The only candidates for Direct2Core are DRS packets destined for Cbos.", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AD_VNA_EQ0", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AD_VNA_EQ0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AD_VNA_EQ1", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AD_VNA_EQ1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AD_VNA_EQ2", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AD_VNA_EQ2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ0", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ0", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ1", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ2", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ2", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ3", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.AK_VNA_EQ3", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_FLOWQ_NO_VNA_CRD.BL_VNA_EQ0", + "EventCode": "0x18", + "EventName": "UNC_UPI_FLOWQ_NO_VNA_CRD.BL_VNA_EQ0", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L1", + "EventCode": "0x21", + "EventName": "UNC_UPI_L1_POWER_CYCLES", + "PerPkg": "1", + "PublicDescription": "Cycles in L1 : Number of UPI qfclk cycles spent in L1 power mode. L1 is a mode that totally shuts down a UPI link. Use edge detect to count the number of instances when the UPI link entered L1. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another. Because L1 totally shuts down the link, it takes a good amount of time to exit this mode.", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_BYP_BLOCKED.BGF_CRD", + "EventCode": "0x14", + "EventName": "UNC_UPI_M3_BYP_BLOCKED.BGF_CRD", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_BYP_BLOCKED.FLOWQ_AD_VNA_LE2", + "EventCode": "0x14", + "EventName": "UNC_UPI_M3_BYP_BLOCKED.FLOWQ_AD_VNA_LE2", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_BYP_BLOCKED.FLOWQ_AK_VNA_LE3", + "EventCode": "0x14", + "EventName": "UNC_UPI_M3_BYP_BLOCKED.FLOWQ_AK_VNA_LE3", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_BYP_BLOCKED.FLOWQ_BL_VNA_EQ0", + "EventCode": "0x14", + "EventName": "UNC_UPI_M3_BYP_BLOCKED.FLOWQ_BL_VNA_EQ0", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_BYP_BLOCKED.GV_BLOCK", + "EventCode": "0x14", + "EventName": "UNC_UPI_M3_BYP_BLOCKED.GV_BLOCK", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_CRD_RETURN_BLOCKED", + "EventCode": "0x16", + "EventName": "UNC_UPI_M3_CRD_RETURN_BLOCKED", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.BGF_CRD", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.BGF_CRD", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_AD_VNA_BTW_2_THRESH", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_AD_VNA_BTW_2_THRESH", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_AD_VNA_LE2", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_AD_VNA_LE2", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_AK_VNA_LE3", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_AK_VNA_LE3", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_BL_VNA_BTW_0_THRESH", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_BL_VNA_BTW_0_THRESH", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_BL_VNA_EQ0", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.FLOWQ_BL_VNA_EQ0", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_M3_RXQ_BLOCKED.GV_BLOCK", + "EventCode": "0x15", + "EventName": "UNC_UPI_M3_RXQ_BLOCKED.GV_BLOCK", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles where phy is not in L0, L0c, L0p, L1", + "EventCode": "0x20", + "EventName": "UNC_UPI_PHY_INIT_CYCLES", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "L1 Req Nack", + "EventCode": "0x23", + "EventName": "UNC_UPI_POWER_L1_NACK", + "PerPkg": "1", + "PublicDescription": "L1 Req Nack : Counts the number of times a link sends/receives a LinkReqNAck. When the UPI links would like to change power state, the Tx side initiates a request to the Rx side requesting to change states. This requests can either be accepted or denied. If the Rx side replies with an Ack, the power mode will change. If it replies with NAck, no change will take place. This can be filtered based on Rx and Tx. An Rx LinkReqNAck refers to receiving an NAck (meaning this agent's Tx originally requested the power change). A Tx LinkReqNAck refers to sending this command (meaning the peer agent's Tx originally requested the power change and this agent accepted it).", + "Unit": "UPI" + }, + { + "BriefDescription": "L1 Req (same as L1 Ack).", + "EventCode": "0x22", + "EventName": "UNC_UPI_POWER_L1_REQ", + "PerPkg": "1", + "PublicDescription": "L1 Req (same as L1 Ack). : Counts the number of times a link sends/receives a LinkReqAck. When the UPI links would like to change power state, the Tx side initiates a request to the Rx side requesting to change states. This requests can either be accepted or denied. If the Rx side replies with an Ack, the power mode will change. If it replies with NAck, no change will take place. This can be filtered based on Rx and Tx. An Rx LinkReqAck refers to receiving an Ack (meaning this agent's Tx originally requested the power change). A Tx LinkReqAck refers to sending this command (meaning the peer agent's Tx originally requested the power change and this agent accepted it).", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_REQ_SLOT2_FROM_M3.ACK", + "EventCode": "0x46", + "EventName": "UNC_UPI_REQ_SLOT2_FROM_M3.ACK", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_REQ_SLOT2_FROM_M3.VN0", + "EventCode": "0x46", + "EventName": "UNC_UPI_REQ_SLOT2_FROM_M3.VN0", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_REQ_SLOT2_FROM_M3.VN1", + "EventCode": "0x46", + "EventName": "UNC_UPI_REQ_SLOT2_FROM_M3.VN1", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_REQ_SLOT2_FROM_M3.VNA", + "EventCode": "0x46", + "EventName": "UNC_UPI_REQ_SLOT2_FROM_M3.VNA", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L0p", + "EventCode": "0x25", + "EventName": "UNC_UPI_RxL0P_POWER_CYCLES", + "PerPkg": "1", + "PublicDescription": "Cycles in L0p : Number of UPI qfclk cycles spent in L0p power mode. L0p is a mode where we disable 1/2 of the UPI lanes, decreasing our bandwidth in order to save power. It increases snoop and data transfer latencies and decreases overall bandwidth. This mode can be very useful in NUMA optimized workloads that largely only utilize UPI for snoops and their responses. Use edge detect to count the number of instances when the UPI link entered L0p. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another.", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L0", + "EventCode": "0x24", + "EventName": "UNC_UPI_RxL0_POWER_CYCLES", + "PerPkg": "1", + "PublicDescription": "Cycles in L0 : Number of UPI qfclk cycles spent in L0 power mode in the Link Layer. L0 is the default mode which provides the highest performance with the most power. Use edge detect to count the number of instances that the link entered L0. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another. The phy layer sometimes leaves L0 for training, which will not be captured by this event.", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.DATA", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.DATA", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.LLCRD", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.LLCRD", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.LLCTRL", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.LLCTRL", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.NULL", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.NULL", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.PROTHDR", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.PROTHDR", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.SLOT0", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.SLOT0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.SLOT1", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.SLOT1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_ANY_FLITS.SLOT2", + "EventCode": "0x4B", + "EventName": "UNC_UPI_RxL_ANY_FLITS.SLOT2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Bypass", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCB", + "PerPkg": "1", + "PublicDescription": "Matches on Receive path of a UPI Port : Non-Coherent Bypass : Matches on Receive path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0xe", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Bypass, Match Opcode", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCB_OPC", + "PerPkg": "1", + "PublicDescription": "Matches on Receive path of a UPI Port : Non-Coherent Bypass, Match Opcode : Matches on Receive path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0x10e", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Standard", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCS", + "PerPkg": "1", + "PublicDescription": "Matches on Receive path of a UPI Port : Non-Coherent Standard : Matches on Receive path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Receive path of a UPI Port : Non-Coherent Standard, Match Opcode", + "EventCode": "0x05", + "EventName": "UNC_UPI_RxL_BASIC_HDR_MATCH.NCS_OPC", + "PerPkg": "1", + "PublicDescription": "Matches on Receive path of a UPI Port : Non-Coherent Standard, Match Opcode : Matches on Receive path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0x10f", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Bypassed : Slot 0", + "EventCode": "0x31", + "EventName": "UNC_UPI_RxL_BYPASSED.SLOT0", + "PerPkg": "1", + "PublicDescription": "RxQ Flit Buffer Bypassed : Slot 0 : Counts the number of times that an incoming flit was able to bypass the flit buffer and pass directly across the BGF and into the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of flits transferred, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Bypassed : Slot 1", + "EventCode": "0x31", + "EventName": "UNC_UPI_RxL_BYPASSED.SLOT1", + "PerPkg": "1", + "PublicDescription": "RxQ Flit Buffer Bypassed : Slot 1 : Counts the number of times that an incoming flit was able to bypass the flit buffer and pass directly across the BGF and into the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of flits transferred, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Bypassed : Slot 2", + "EventCode": "0x31", + "EventName": "UNC_UPI_RxL_BYPASSED.SLOT2", + "PerPkg": "1", + "PublicDescription": "RxQ Flit Buffer Bypassed : Slot 2 : Counts the number of times that an incoming flit was able to bypass the flit buffer and pass directly across the BGF and into the Egress. This is a latency optimization, and should generally be the common case. If this value is less than the number of flits transferred, it implies that there was queueing getting onto the ring, and thus the transactions saw higher latency.", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "CRC Errors Detected", + "EventCode": "0x0b", + "EventName": "UNC_UPI_RxL_CRC_ERRORS", + "PerPkg": "1", + "PublicDescription": "CRC Errors Detected : Number of CRC errors detected in the UPI Agent. Each UPI flit incorporates 8 bits of CRC for error detection. This counts the number of flits where the CRC was able to detect an error. After an error has been detected, the UPI agent will send a request to the transmitting socket to resend the flit (as well as any flits that came after it).", + "Unit": "UPI" + }, + { + "BriefDescription": "LLR Requests Sent", + "EventCode": "0x08", + "EventName": "UNC_UPI_RxL_CRC_LLR_REQ_TRANSMIT", + "PerPkg": "1", + "PublicDescription": "LLR Requests Sent : Number of LLR Requests were transmitted. This should generally be <= the number of CRC errors detected. If multiple errors are detected before the Rx side receives a LLC_REQ_ACK from the Tx side, there is no need to send more LLR_REQ_NACKs..", + "Unit": "UPI" + }, + { + "BriefDescription": "VN0 Credit Consumed", + "EventCode": "0x39", + "EventName": "UNC_UPI_RxL_CREDITS_CONSUMED_VN0", + "PerPkg": "1", + "PublicDescription": "VN0 Credit Consumed : Counts the number of times that an RxQ VN0 credit was consumed (i.e. message uses a VN0 credit for the Rx Buffer). This includes packets that went through the RxQ and those that were bypasssed.", + "Unit": "UPI" + }, + { + "BriefDescription": "VN1 Credit Consumed", + "EventCode": "0x3a", + "EventName": "UNC_UPI_RxL_CREDITS_CONSUMED_VN1", + "PerPkg": "1", + "PublicDescription": "VN1 Credit Consumed : Counts the number of times that an RxQ VN1 credit was consumed (i.e. message uses a VN1 credit for the Rx Buffer). This includes packets that went through the RxQ and those that were bypasssed.", + "Unit": "UPI" + }, + { + "BriefDescription": "VNA Credit Consumed", + "EventCode": "0x38", + "EventName": "UNC_UPI_RxL_CREDITS_CONSUMED_VNA", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of times that an RxQ VNA credit was consumed (i.e. message uses a VNA credit for the Rx Buffer). This includes packets that went through the RxQ and those that were bypasssed.", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : All Data", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.ALL_DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : All Data : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Null FLITs received from any slot", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.ALL_NULL", + "PerPkg": "1", + "UMask": "0x27", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Data", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Data : Shows legal flit time (hides impact of L0p and L0c). : Count Data Flits (which consume all slots), but how much to count is based on Slot0-2 mask, so count can be 0-3 depending on which slots are enabled for counting..", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Idle", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.IDLE", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Idle : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x47", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : LLCRD Not Empty", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.LLCRD", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : LLCRD Not Empty : Shows legal flit time (hides impact of L0p and L0c). : Enables counting of LLCRD (with non-zero payload). This only applies to slot 2 since LLCRD is only allowed in slot 2", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : LLCTRL", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.LLCTRL", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : LLCTRL : Shows legal flit time (hides impact of L0p and L0c). : Equivalent to an idle packet. Enables counting of slot 0 LLCTRL messages.", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : All Non Data", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.NON_DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : All Non Data : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x97", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot NULL or LLCRD Empty", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.NULL", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Slot NULL or LLCRD Empty : Shows legal flit time (hides impact of L0p and L0c). : LLCRD with all zeros is treated as NULL. Slot 1 is not treated as NULL if slot 0 is a dual slot. This can apply to slot 0,1, or 2.", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Protocol Header", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.PROTHDR", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Protocol Header : Shows legal flit time (hides impact of L0p and L0c). : Enables count of protocol headers in slot 0,1,2 (depending on slot uMask bits)", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot 0", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.SLOT0", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Slot 0 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 0 - Other mask bits determine types of headers to count.", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot 1", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.SLOT1", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Slot 1 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 1 - Other mask bits determine types of headers to count.", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Received : Slot 2", + "EventCode": "0x03", + "EventName": "UNC_UPI_RxL_FLITS.SLOT2", + "PerPkg": "1", + "PublicDescription": "Valid Flits Received : Slot 2 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 2 - Other mask bits determine types of headers to count.", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Allocations : Slot 0", + "EventCode": "0x30", + "EventName": "UNC_UPI_RxL_INSERTS.SLOT0", + "PerPkg": "1", + "PublicDescription": "RxQ Flit Buffer Allocations : Slot 0 : Number of allocations into the UPI Rx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Allocations : Slot 1", + "EventCode": "0x30", + "EventName": "UNC_UPI_RxL_INSERTS.SLOT1", + "PerPkg": "1", + "PublicDescription": "RxQ Flit Buffer Allocations : Slot 1 : Number of allocations into the UPI Rx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Flit Buffer Allocations : Slot 2", + "EventCode": "0x30", + "EventName": "UNC_UPI_RxL_INSERTS.SLOT2", + "PerPkg": "1", + "PublicDescription": "RxQ Flit Buffer Allocations : Slot 2 : Number of allocations into the UPI Rx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Occupancy - All Packets : Slot 0", + "EventCode": "0x32", + "EventName": "UNC_UPI_RxL_OCCUPANCY.SLOT0", + "PerPkg": "1", + "PublicDescription": "RxQ Occupancy - All Packets : Slot 0 : Accumulates the number of elements in the UPI RxQ in each cycle. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Occupancy - All Packets : Slot 1", + "EventCode": "0x32", + "EventName": "UNC_UPI_RxL_OCCUPANCY.SLOT1", + "PerPkg": "1", + "PublicDescription": "RxQ Occupancy - All Packets : Slot 1 : Accumulates the number of elements in the UPI RxQ in each cycle. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "RxQ Occupancy - All Packets : Slot 2", + "EventCode": "0x32", + "EventName": "UNC_UPI_RxL_OCCUPANCY.SLOT2", + "PerPkg": "1", + "PublicDescription": "RxQ Occupancy - All Packets : Slot 2 : Accumulates the number of elements in the UPI RxQ in each cycle. Generally, when data is transmitted across UPI, it will bypass the RxQ and pass directly to the ring interface. If things back up getting transmitted onto the ring, however, it may need to allocate into this buffer, thus increasing the latency. This event can be used in conjunction with the Flit Buffer Not Empty event to calculate average occupancy, or with the Flit Buffer Allocations event to track average lifetime.", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_SLOT_BYPASS.S0_RXQ1", + "EventCode": "0x33", + "EventName": "UNC_UPI_RxL_SLOT_BYPASS.S0_RXQ1", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_SLOT_BYPASS.S0_RXQ2", + "EventCode": "0x33", + "EventName": "UNC_UPI_RxL_SLOT_BYPASS.S0_RXQ2", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_SLOT_BYPASS.S1_RXQ0", + "EventCode": "0x33", + "EventName": "UNC_UPI_RxL_SLOT_BYPASS.S1_RXQ0", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_SLOT_BYPASS.S1_RXQ2", + "EventCode": "0x33", + "EventName": "UNC_UPI_RxL_SLOT_BYPASS.S1_RXQ2", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_SLOT_BYPASS.S2_RXQ0", + "EventCode": "0x33", + "EventName": "UNC_UPI_RxL_SLOT_BYPASS.S2_RXQ0", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_RxL_SLOT_BYPASS.S2_RXQ1", + "EventCode": "0x33", + "EventName": "UNC_UPI_RxL_SLOT_BYPASS.S2_RXQ1", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.CFG_CTL", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.CFG_CTL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.DFX", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.DFX", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.RETRY", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.RETRY", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.RXQ", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.RXQ", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.RXQ_BYPASS", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.RXQ_BYPASS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.RXQ_CRED", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.RXQ_CRED", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.SPARE", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.SPARE", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_CLK_ACTIVE.TXQ", + "EventCode": "0x2a", + "EventName": "UNC_UPI_TxL0P_CLK_ACTIVE.TXQ", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L0p", + "EventCode": "0x27", + "EventName": "UNC_UPI_TxL0P_POWER_CYCLES", + "PerPkg": "1", + "PublicDescription": "Cycles in L0p : Number of UPI qfclk cycles spent in L0p power mode. L0p is a mode where we disable 1/2 of the UPI lanes, decreasing our bandwidth in order to save power. It increases snoop and data transfer latencies and decreases overall bandwidth. This mode can be very useful in NUMA optimized workloads that largely only utilize UPI for snoops and their responses. Use edge detect to count the number of instances when the UPI link entered L0p. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another.", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_POWER_CYCLES_LL_ENTER", + "EventCode": "0x28", + "EventName": "UNC_UPI_TxL0P_POWER_CYCLES_LL_ENTER", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL0P_POWER_CYCLES_M3_EXIT", + "EventCode": "0x29", + "EventName": "UNC_UPI_TxL0P_POWER_CYCLES_M3_EXIT", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "Cycles in L0", + "EventCode": "0x26", + "EventName": "UNC_UPI_TxL0_POWER_CYCLES", + "PerPkg": "1", + "PublicDescription": "Cycles in L0 : Number of UPI qfclk cycles spent in L0 power mode in the Link Layer. L0 is the default mode which provides the highest performance with the most power. Use edge detect to count the number of instances that the link entered L0. Link power states are per link and per direction, so for example the Tx direction could be in one state while Rx was in another. The phy layer sometimes leaves L0 for training, which will not be captured by this event.", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.DATA", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.DATA", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.LLCRD", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.LLCRD", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.LLCTRL", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.LLCTRL", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.NULL", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.NULL", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.PROTHDR", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.PROTHDR", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.SLOT0", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.SLOT0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.SLOT1", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.SLOT1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_TxL_ANY_FLITS.SLOT2", + "EventCode": "0x4A", + "EventName": "UNC_UPI_TxL_ANY_FLITS.SLOT2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Bypass", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCB", + "PerPkg": "1", + "PublicDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Bypass : Matches on Transmit path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0xe", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Bypass, Match Opcode", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCB_OPC", + "PerPkg": "1", + "PublicDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Bypass, Match Opcode : Matches on Transmit path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0x10e", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Standard", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCS", + "PerPkg": "1", + "PublicDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Standard : Matches on Transmit path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Standard, Match Opcode", + "EventCode": "0x04", + "EventName": "UNC_UPI_TxL_BASIC_HDR_MATCH.NCS_OPC", + "PerPkg": "1", + "PublicDescription": "Matches on Transmit path of a UPI Port : Non-Coherent Standard, Match Opcode : Matches on Transmit path of a UPI port.\r\nMatch based on UMask specific bits:\r\nZ: Message Class (3-bit)\r\nY: Message Class Enable\r\nW: Opcode (4-bit)\r\nV: Opcode Enable\r\nU: Local Enable\r\nT: Remote Enable\r\nS: Data Hdr Enable\r\nR: Non-Data Hdr Enable\r\nQ: Dual Slot Hdr Enable\r\nP: Single Slot Hdr Enable\r\nLink Layer control types are excluded (LL CTRL, slot NULL, LLCRD) even under specific opcode match_en cases.\r\nNote: If Message Class is disabled, we expect opcode to also be disabled.", + "UMask": "0x10f", + "Unit": "UPI" + }, + { + "BriefDescription": "Tx Flit Buffer Bypassed", + "EventCode": "0x41", + "EventName": "UNC_UPI_TxL_BYPASSED", + "PerPkg": "1", + "PublicDescription": "Tx Flit Buffer Bypassed : Counts the number of times that an incoming flit was able to bypass the Tx flit buffer and pass directly out the UPI Link. Generally, when data is transmitted across UPI, it will bypass the TxQ and pass directly to the link. However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link.", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All Data", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : All Data : Counts number of data flits across this UPI link.", + "UMask": "0xf", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All LLCRD Not Empty", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_LLCRD", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : All Data : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x17", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All LLCTRL", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_LLCTRL", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : All LLCTRL : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x47", + "Unit": "UPI" + }, + { + "BriefDescription": "All Null Flits", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_NULL", + "PerPkg": "1", + "UMask": "0x27", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All Protocol Header", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.ALL_PROTHDR", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : All ProtDDR : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x87", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Data", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Data : Shows legal flit time (hides impact of L0p and L0c). : Count Data Flits (which consume all slots), but how much to count is based on Slot0-2 mask, so count can be 0-3 depending on which slots are enabled for counting..", + "UMask": "0x8", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Idle", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.IDLE", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Idle : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x47", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : LLCRD Not Empty", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.LLCRD", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : LLCRD Not Empty : Shows legal flit time (hides impact of L0p and L0c). : Enables counting of LLCRD (with non-zero payload). This only applies to slot 2 since LLCRD is only allowed in slot 2", + "UMask": "0x10", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : LLCTRL", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.LLCTRL", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : LLCTRL : Shows legal flit time (hides impact of L0p and L0c). : Equivalent to an idle packet. Enables counting of slot 0 LLCTRL messages.", + "UMask": "0x40", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : All Non Data", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.NON_DATA", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : All Non Data : Shows legal flit time (hides impact of L0p and L0c).", + "UMask": "0x97", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot NULL or LLCRD Empty", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.NULL", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Slot NULL or LLCRD Empty : Shows legal flit time (hides impact of L0p and L0c). : LLCRD with all zeros is treated as NULL. Slot 1 is not treated as NULL if slot 0 is a dual slot. This can apply to slot 0,1, or 2.", + "UMask": "0x20", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Protocol Header", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.PROTHDR", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Protocol Header : Shows legal flit time (hides impact of L0p and L0c). : Enables count of protocol headers in slot 0,1,2 (depending on slot uMask bits)", + "UMask": "0x80", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot 0", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.SLOT0", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Slot 0 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 0 - Other mask bits determine types of headers to count.", + "UMask": "0x1", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot 1", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.SLOT1", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Slot 1 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 1 - Other mask bits determine types of headers to count.", + "UMask": "0x2", + "Unit": "UPI" + }, + { + "BriefDescription": "Valid Flits Sent : Slot 2", + "EventCode": "0x02", + "EventName": "UNC_UPI_TxL_FLITS.SLOT2", + "PerPkg": "1", + "PublicDescription": "Valid Flits Sent : Slot 2 : Shows legal flit time (hides impact of L0p and L0c). : Count Slot 2 - Other mask bits determine types of headers to count.", + "UMask": "0x4", + "Unit": "UPI" + }, + { + "BriefDescription": "Tx Flit Buffer Allocations", + "EventCode": "0x40", + "EventName": "UNC_UPI_TxL_INSERTS", + "PerPkg": "1", + "PublicDescription": "Tx Flit Buffer Allocations : Number of allocations into the UPI Tx Flit Buffer. Generally, when data is transmitted across UPI, it will bypass the TxQ and pass directly to the link. However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link. This event can be used in conjunction with the Flit Buffer Occupancy event in order to calculate the average flit buffer lifetime.", + "Unit": "UPI" + }, + { + "BriefDescription": "Tx Flit Buffer Occupancy", + "EventCode": "0x42", + "EventName": "UNC_UPI_TxL_OCCUPANCY", + "PerPkg": "1", + "PublicDescription": "Tx Flit Buffer Occupancy : Accumulates the number of flits in the TxQ. Generally, when data is transmitted across UPI, it will bypass the TxQ and pass directly to the link. However, the TxQ will be used with L0p and when LLR occurs, increasing latency to transfer out to the link. This can be used with the cycles not empty event to track average occupancy, or the allocations event to track average lifetime in the TxQ.", + "Unit": "UPI" + }, + { + "BriefDescription": "UNC_UPI_VNA_CREDIT_RETURN_BLOCKED_VN01", + "EventCode": "0x45", + "EventName": "UNC_UPI_VNA_CREDIT_RETURN_BLOCKED_VN01", + "PerPkg": "1", + "Unit": "UPI" + }, + { + "BriefDescription": "VNA Credits Pending Return - Occupancy", + "EventCode": "0x44", + "EventName": "UNC_UPI_VNA_CREDIT_RETURN_OCCUPANCY", + "PerPkg": "1", + "PublicDescription": "VNA Credits Pending Return - Occupancy : Number of VNA credits in the Rx side that are waitng to be returned back across the link.", + "Unit": "UPI" + }, + { + "BriefDescription": "Message Received : Doorbell", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.DOORBELL_RCVD", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : Interrupt", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.INT_PRIO", + "PerPkg": "1", + "PublicDescription": "Message Received : Interrupt : Interrupts", + "UMask": "0x10", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : IPI", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.IPI_RCVD", + "PerPkg": "1", + "PublicDescription": "Message Received : IPI : Inter Processor Interrupts", + "UMask": "0x4", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : MSI", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.MSI_RCVD", + "PerPkg": "1", + "PublicDescription": "Message Received : MSI : Message Signaled Interrupts - interrupts sent by devices (including PCIe via IOxAPIC) (Socket Mode only)", + "UMask": "0x2", + "Unit": "UBOX" + }, + { + "BriefDescription": "Message Received : VLW", + "EventCode": "0x42", + "EventName": "UNC_U_EVENT_MSG.VLW_RCVD", + "PerPkg": "1", + "PublicDescription": "Message Received : VLW : Virtual Logical Wire (legacy) message were received from Uncore.", + "UMask": "0x1", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_CBO_NCB", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_CBO_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_CBO_NCS", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_CBO_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_UPI_NCB", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_UPI_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_UPI_NCS", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.RxC_CYCLES_NE_UPI_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_CBO_NCB", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_CBO_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_CBO_NCS", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_CBO_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_UPI_NCB", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_UPI_NCB", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_UPI_NCS", + "EventCode": "0x4d", + "EventName": "UNC_U_M2U_MISC1.TxC_CYCLES_CRD_OVF_UPI_NCS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.RxC_CYCLES_EMPTY_BL", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.RxC_CYCLES_EMPTY_BL", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.RxC_CYCLES_FULL_BL", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.RxC_CYCLES_FULL_BL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.TxC_CYCLES_CRD_OVF_VN0_NCB", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.TxC_CYCLES_CRD_OVF_VN0_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.TxC_CYCLES_CRD_OVF_VN0_NCS", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.TxC_CYCLES_CRD_OVF_VN0_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.TxC_CYCLES_EMPTY_AK", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.TxC_CYCLES_EMPTY_AK", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.TxC_CYCLES_EMPTY_AKC", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.TxC_CYCLES_EMPTY_AKC", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.TxC_CYCLES_EMPTY_BL", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.TxC_CYCLES_EMPTY_BL", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC2.TxC_CYCLES_FULL_BL", + "EventCode": "0x4e", + "EventName": "UNC_U_M2U_MISC2.TxC_CYCLES_FULL_BL", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC3.TxC_CYCLES_FULL_AK", + "EventCode": "0x4f", + "EventName": "UNC_U_M2U_MISC3.TxC_CYCLES_FULL_AK", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_M2U_MISC3.TxC_CYCLES_FULL_AKC", + "EventCode": "0x4f", + "EventName": "UNC_U_M2U_MISC3.TxC_CYCLES_FULL_AKC", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UBOX" + }, + { + "BriefDescription": "Cycles PHOLD Assert to Ack : Assert to ACK", + "EventCode": "0x45", + "EventName": "UNC_U_PHOLD_CYCLES.ASSERT_TO_ACK", + "PerPkg": "1", + "PublicDescription": "Cycles PHOLD Assert to Ack : Assert to ACK : PHOLD cycles.", + "UMask": "0x1", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_RACU_DRNG.PFTCH_BUF_EMPTY", + "EventCode": "0x4c", + "EventName": "UNC_U_RACU_DRNG.PFTCH_BUF_EMPTY", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_RACU_DRNG.RDRAND", + "EventCode": "0x4c", + "EventName": "UNC_U_RACU_DRNG.RDRAND", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "UBOX" + }, + { + "BriefDescription": "UNC_U_RACU_DRNG.RDSEED", + "EventCode": "0x4c", + "EventName": "UNC_U_RACU_DRNG.RDSEED", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "UBOX" + }, + { + "BriefDescription": "RACU Request", + "EventCode": "0x46", + "EventName": "UNC_U_RACU_REQUESTS", + "PerPkg": "1", + "PublicDescription": "RACU Request : Number outstanding register requests within message channel tracker", + "Unit": "UBOX" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-io.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-io.json new file mode 100644 index 000000000000..557080b74ee5 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-io.json @@ -0,0 +1,3587 @@ +[ + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART0_FREERUN", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART1_FREERUN", + "PerPkg": "1", + "UMask": "0x21", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART2_FREERUN", + "PerPkg": "1", + "UMask": "0x22", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART3_FREERUN", + "PerPkg": "1", + "UMask": "0x23", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART4_FREERUN", + "PerPkg": "1", + "UMask": "0x24", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART5_FREERUN", + "PerPkg": "1", + "UMask": "0x25", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART6_FREERUN", + "PerPkg": "1", + "UMask": "0x26", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "Free running counter that increments for every 32 bytes of data sent from the IO agent to the SOC", + "EventCode": "0xff", + "EventName": "UNC_IIO_BANDWIDTH_IN.PART7_FREERUN", + "PerPkg": "1", + "UMask": "0x27", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "IIO Clockticks", + "EventCode": "0x01", + "EventName": "UNC_IIO_CLOCKTICKS", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "Number of IIO clock cycles while the event is enabled", + "Unit": "IIO" + }, + { + "BriefDescription": "Free running counter that increments for IIO clocktick", + "EventCode": "0xff", + "EventName": "UNC_IIO_CLOCKTICKS_FREERUN", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iio_free_running" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0-7", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0xff", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 0-7", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 0", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 0 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7001004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 1", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 1 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 1", + "UMask": "0x7002004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 2", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 2 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 2", + "UMask": "0x7004004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 3", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 2 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 3", + "UMask": "0x7008004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 4", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 0 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 4", + "UMask": "0x7010004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 5", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 1 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 5", + "UMask": "0x7020004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 6", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 2 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 6", + "UMask": "0x7040004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Inserts of completions with data: Part 7", + "EventCode": "0xc2", + "EventName": "UNC_IIO_COMP_BUF_INSERTS.CMPD.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "PCIe Completion Buffer Inserts of completions with data : Part 2 : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 7", + "UMask": "0x7080004", + "Unit": "IIO" + }, + { + "BriefDescription": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.ALL_PARTS", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "UMask": "0xff", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 0", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7000001", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 1", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x4 card is plugged in to slot 1", + "UMask": "0x7000002", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 2", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7000004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 3", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x4 card is plugged in to slot 3", + "UMask": "0x7000008", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 4", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7000010", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 5", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x4 card is plugged in to slot 1", + "UMask": "0x7000020", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 6", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7000040", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Completion Buffer Occupancy : Part 7", + "EventCode": "0xd5", + "EventName": "UNC_IIO_COMP_BUF_OCCUPANCY.CMPD.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "x4 card is plugged in to slot 3", + "UMask": "0x7000080", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part0-7", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00ff", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part0", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested by the CPU : Core reading from Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7001004", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part1", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested by the CPU : Core reading from Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7002004", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part2", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested by the CPU : Core reading from Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7004004", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by the CPU to IIO Part3", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested by the CPU : Core reading from Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7008004", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested by the CPU : Core reading from Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7010004", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested by the CPU : Core reading from Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7020004", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested by the CPU : Core reading from Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7040004", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested by the CPU : Core reading from Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7080004", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made to IIO Part0-7 by the CPU", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00ff", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.IOMMU0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0100", + "PublicDescription": "Data requested by the CPU : Core writing to Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : IOMMU - Type 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.IOMMU1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0200", + "PublicDescription": "Data requested by the CPU : Core writing to Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : IOMMU - Type 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made to IIO Part0 by the CPU", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested by the CPU : Core writing to Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made to IIO Part1 by the CPU", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested by the CPU : Core writing to Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made to IIO Part2 by the CPU", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested by the CPU : Core writing to Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made to IIO Part3 by the CPU", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested by the CPU : Core writing to Card's MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested by the CPU : Core writing to Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested by the CPU : Core writing to Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested by the CPU : Core writing to Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested by the CPU : Core writing to Cards MMIO space : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer read request for 4 bytes made by a different IIO unit to IIO Part0", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7001008", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer read request for 4 bytes made by a different IIO unit to IIO Part0", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7002008", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer read request for 4 bytes made by a different IIO unit to IIO Part0", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7004008", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer read request for 4 bytes made by a different IIO unit to IIO Part0", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7008008", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7010008", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7020008", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7040008", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) reading from this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7080008", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made to IIO Part0 by a different IIO unit", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7001002", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made to IIO Part0 by a different IIO unit", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7002002", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made to IIO Part0 by a different IIO unit", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7004002", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made to IIO Part0 by a different IIO unit", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7008002", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7010002", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7020002", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x7040002", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc0", + "EventName": "UNC_IIO_DATA_REQ_BY_CPU.PEER_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested by the CPU : Another card (different IIO stack) writing to this card. : Number of DWs (4 bytes) requested by the main die. Includes all requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7080002", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0xff", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 2", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 4/5/6/7, Or x8 card plugged in to Lane 4/5, Or x4 card is plugged in to slot 4", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 5", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 6/7, Or x4 card is plugged in to slot 6", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.CMPD.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested of the CPU : CmpD - device sending completion to CPU request : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 7", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by IIO Part0-7 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00ff", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by IIO Part0 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by IIO Part1 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by IIO Part2 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for 4 bytes made by IIO Part3 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card reading from DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested of the CPU : Card reading from DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made by IIO Part0-7 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.ALL_PARTS", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00ff", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made by IIO Part0 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made by IIO Part1 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made by IIO Part2 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of 4 bytes made by IIO Part3 to Memory", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to DRAM", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested of the CPU : Card writing to DRAM : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made by IIO Part0 to an IIO target", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made by IIO Part0 to an IIO target", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made by IIO Part0 to an IIO target", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Peer to peer write request of 4 bytes made by IIO Part0 to an IIO target", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Data requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x83", + "EventName": "UNC_IIO_DATA_REQ_OF_CPU.PEER_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Data requested of the CPU : Card writing to another Card (same or different stack) : Number of DWs (4 bytes) the card requests of the main die. Includes all requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests : Passing data to be written", + "EventCode": "0x86", + "EventName": "UNC_IIO_INBOUND_ARB_REQ.DATA", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests : Passing data to be written : How often different queues (e.g. channel / fc) ask to send request into pipeline : Only for posted requests", + "UMask": "0x70ff020", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests : Issuing final read or write of line", + "EventCode": "0x86", + "EventName": "UNC_IIO_INBOUND_ARB_REQ.FINAL_RD_WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests : Issuing final read or write of line : How often different queues (e.g. channel / fc) ask to send request into pipeline", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests : Processing response from IOMMU", + "EventCode": "0x86", + "EventName": "UNC_IIO_INBOUND_ARB_REQ.IOMMU_HIT", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests : Processing response from IOMMU : How often different queues (e.g. channel / fc) ask to send request into pipeline", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests : Issuing to IOMMU", + "EventCode": "0x86", + "EventName": "UNC_IIO_INBOUND_ARB_REQ.IOMMU_REQ", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests : Issuing to IOMMU : How often different queues (e.g. channel / fc) ask to send request into pipeline", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests : Request Ownership", + "EventCode": "0x86", + "EventName": "UNC_IIO_INBOUND_ARB_REQ.REQ_OWN", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests : Request Ownership : How often different queues (e.g. channel / fc) ask to send request into pipeline : Only for posted requests", + "UMask": "0x70ff004", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests : Writing line", + "EventCode": "0x86", + "EventName": "UNC_IIO_INBOUND_ARB_REQ.WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests : Writing line : How often different queues (e.g. channel / fc) ask to send request into pipeline : Only for posted requests", + "UMask": "0x70ff010", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests granted : Passing data to be written", + "EventCode": "0x87", + "EventName": "UNC_IIO_INBOUND_ARB_WON.DATA", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests granted : Passing data to be written : How often different queues (e.g. channel / fc) are allowed to send request into pipeline : Only for posted requests", + "UMask": "0x70ff020", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests granted : Issuing final read or write of line", + "EventCode": "0x87", + "EventName": "UNC_IIO_INBOUND_ARB_WON.FINAL_RD_WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests granted : Issuing final read or write of line : How often different queues (e.g. channel / fc) are allowed to send request into pipeline", + "UMask": "0x70ff008", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests granted : Processing response from IOMMU", + "EventCode": "0x87", + "EventName": "UNC_IIO_INBOUND_ARB_WON.IOMMU_HIT", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests granted : Processing response from IOMMU : How often different queues (e.g. channel / fc) are allowed to send request into pipeline", + "UMask": "0x70ff002", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests granted : Issuing to IOMMU", + "EventCode": "0x87", + "EventName": "UNC_IIO_INBOUND_ARB_WON.IOMMU_REQ", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests granted : Issuing to IOMMU : How often different queues (e.g. channel / fc) are allowed to send request into pipeline", + "UMask": "0x70ff001", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests granted : Request Ownership", + "EventCode": "0x87", + "EventName": "UNC_IIO_INBOUND_ARB_WON.REQ_OWN", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests granted : Request Ownership : How often different queues (e.g. channel / fc) are allowed to send request into pipeline : Only for posted requests", + "UMask": "0x70ff004", + "Unit": "IIO" + }, + { + "BriefDescription": "Incoming arbitration requests granted : Writing line", + "EventCode": "0x87", + "EventName": "UNC_IIO_INBOUND_ARB_WON.WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Incoming arbitration requests granted : Writing line : How often different queues (e.g. channel / fc) are allowed to send request into pipeline : Only for posted requests", + "UMask": "0x70ff010", + "Unit": "IIO" + }, + { + "BriefDescription": ": Context cache hits", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.CTXT_CACHE_HITS", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": ": Context cache hits : Counts each time a first look up of the transaction hits the RCC.", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": ": Context cache lookups", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.CTXT_CACHE_LOOKUPS", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": ": Context cache lookups : Counts each time a transaction looks up root context cache.", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": ": IOTLB lookups first", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.FIRST_LOOKUPS", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": ": IOTLB lookups first : Some transactions have to look up IOTLB multiple times. Counts the first time a request looks up IOTLB.", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "IOTLB Fills (same as IOTLB miss)", + "EventCode": "0x40", + "EventName": "UNC_IIO_IOMMU0.MISSES", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "IOTLB Fills (same as IOTLB miss) : When a transaction misses IOTLB, it does a page walk to look up memory and bring in the relevant page translation. Counts when this page translation is written to IOTLB.", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": ": IOMMU memory access", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.NUM_MEM_ACCESSES", + "PerPkg": "1", + "PublicDescription": ": IOMMU memory access : IOMMU sends out memory fetches when it misses the cache look up which is indicated by this signal. M2IOSF only uses low priority channel", + "UMask": "0xc0", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWC Hit to a 2M page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.PWC_1G_HITS", + "PerPkg": "1", + "PublicDescription": ": PWC Hit to a 2M page : Counts each time a transaction's first look up hits the SLPWC at the 2M level", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWT Hit to a 256T page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.PWC_256T_HITS", + "PerPkg": "1", + "PublicDescription": ": PWT Hit to a 256T page : Counts each time a transaction's first look up hits the SLPWC at the 512G level", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWC Hit to a 4K page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.PWC_2M_HITS", + "PerPkg": "1", + "PublicDescription": ": PWC Hit to a 4K page : Counts each time a transaction's first look up hits the SLPWC at the 4K level", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWC Hit to a 1G page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.PWC_512G_HITS", + "PerPkg": "1", + "PublicDescription": ": PWC Hit to a 1G page : Counts each time a transaction's first look up hits the SLPWC at the 1G level", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": ": PageWalk cache fill", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.PWC_CACHE_FILLS", + "PerPkg": "1", + "PublicDescription": ": PageWalk cache fill : When a transaction misses SLPWC, it does a page walk to look up memory and bring in the relevant page translation. When this page translation is written to SLPWC, ObsPwcFillValid_nnnH is asserted.", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": ": PageWalk cache lookup", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.PWT_CACHE_LOOKUPS", + "PerPkg": "1", + "PublicDescription": ": PageWalk cache lookup : Counts each time a transaction looks up second level page walk cache.", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWC Hit to a 2M page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_1G_HITS", + "PerPkg": "1", + "PublicDescription": ": PWC Hit to a 2M page : Counts each time a transaction's first look up hits the SLPWC at the 2M level", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWC Hit to a 2M page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_256T_HITS", + "PerPkg": "1", + "PublicDescription": ": PWC Hit to a 2M page : Counts each time a transaction's first look up hits the SLPWC at the 2M level", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": ": PWC Hit to a 1G page", + "EventCode": "0x41", + "EventName": "UNC_IIO_IOMMU1.SLPWC_512G_HITS", + "PerPkg": "1", + "PublicDescription": ": PWC Hit to a 1G page : Counts each time a transaction's first look up hits the SLPWC at the 1G level", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": ": Global IOTLB invalidation cycles", + "EventCode": "0x43", + "EventName": "UNC_IIO_IOMMU3.PWT_OCCUPANCY_MSB", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": ": Global IOTLB invalidation cycles : Indicates that IOMMU is doing global invalidation.", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "AND Mask/match for debug bus : Non-PCIE bus", + "EventCode": "0x02", + "EventName": "UNC_IIO_MASK_MATCH_AND.BUS0", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "AND Mask/match for debug bus : Non-PCIE bus : Asserted if all bits specified by mask match", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "AND Mask/match for debug bus : Non-PCIE bus and PCIE bus", + "EventCode": "0x02", + "EventName": "UNC_IIO_MASK_MATCH_AND.BUS0_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "AND Mask/match for debug bus : Non-PCIE bus and PCIE bus : Asserted if all bits specified by mask match", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "AND Mask/match for debug bus : Non-PCIE bus and !(PCIE bus)", + "EventCode": "0x02", + "EventName": "UNC_IIO_MASK_MATCH_AND.BUS0_NOT_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "AND Mask/match for debug bus : Non-PCIE bus and !(PCIE bus) : Asserted if all bits specified by mask match", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "AND Mask/match for debug bus : PCIE bus", + "EventCode": "0x02", + "EventName": "UNC_IIO_MASK_MATCH_AND.BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "AND Mask/match for debug bus : PCIE bus : Asserted if all bits specified by mask match", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "AND Mask/match for debug bus : !(Non-PCIE bus) and PCIE bus", + "EventCode": "0x02", + "EventName": "UNC_IIO_MASK_MATCH_AND.NOT_BUS0_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "AND Mask/match for debug bus : !(Non-PCIE bus) and PCIE bus : Asserted if all bits specified by mask match", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "AND Mask/match for debug bus : !(Non-PCIE bus) and !(PCIE bus)", + "EventCode": "0x02", + "EventName": "UNC_IIO_MASK_MATCH_AND.NOT_BUS0_NOT_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "AND Mask/match for debug bus : !(Non-PCIE bus) and !(PCIE bus) : Asserted if all bits specified by mask match", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "OR Mask/match for debug bus : Non-PCIE bus", + "EventCode": "0x03", + "EventName": "UNC_IIO_MASK_MATCH_OR.BUS0", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "OR Mask/match for debug bus : Non-PCIE bus : Asserted if any bits specified by mask match", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "OR Mask/match for debug bus : Non-PCIE bus and PCIE bus", + "EventCode": "0x03", + "EventName": "UNC_IIO_MASK_MATCH_OR.BUS0_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "OR Mask/match for debug bus : Non-PCIE bus and PCIE bus : Asserted if any bits specified by mask match", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "OR Mask/match for debug bus : Non-PCIE bus and !(PCIE bus)", + "EventCode": "0x03", + "EventName": "UNC_IIO_MASK_MATCH_OR.BUS0_NOT_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "OR Mask/match for debug bus : Non-PCIE bus and !(PCIE bus) : Asserted if any bits specified by mask match", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "OR Mask/match for debug bus : PCIE bus", + "EventCode": "0x03", + "EventName": "UNC_IIO_MASK_MATCH_OR.BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "OR Mask/match for debug bus : PCIE bus : Asserted if any bits specified by mask match", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "OR Mask/match for debug bus : !(Non-PCIE bus) and PCIE bus", + "EventCode": "0x03", + "EventName": "UNC_IIO_MASK_MATCH_OR.NOT_BUS0_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "OR Mask/match for debug bus : !(Non-PCIE bus) and PCIE bus : Asserted if any bits specified by mask match", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "OR Mask/match for debug bus : !(Non-PCIE bus) and !(PCIE bus)", + "EventCode": "0x03", + "EventName": "UNC_IIO_MASK_MATCH_OR.NOT_BUS0_NOT_BUS1", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "OR Mask/match for debug bus : !(Non-PCIE bus) and !(PCIE bus) : Asserted if any bits specified by mask match", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "Number requests PCIe makes of the main die : All", + "EventCode": "0x85", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU.COMMIT.ALL", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0FFF", + "PublicDescription": "Number requests PCIe makes of the main die : All : Counts full PCIe requests before they're broken into a series of cache-line size requests as measured by DATA_REQ_OF_CPU and TXN_REQ_OF_CPU.", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Abort", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.ABORT", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Confined P2P", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.CONFINED_P2P", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x40", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Local P2P", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.LOC_P2P", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x20", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Multi-cast", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MCAST", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Memory", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MEM", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : MsgB", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.MSGB", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Remote P2P", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.REM_P2P", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x10", + "Unit": "IIO" + }, + { + "BriefDescription": "Num requests sent by PCIe - by target : Ubox", + "EventCode": "0x8e", + "EventName": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "ITC address map 1", + "EventCode": "0x8f", + "EventName": "UNC_IIO_NUM_TGT_MATCHED_REQ_OF_CPU", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "UNC_IIO_NUM_TGT_MATCHED_REQ_OF_CPU", + "Unit": "IIO" + }, + { + "BriefDescription": "Outbound cacheline requests issued : 64B requests issued to device", + "EventCode": "0xd0", + "EventName": "UNC_IIO_OUTBOUND_CL_REQS_ISSUED.TO_IO", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Outbound cacheline requests issued : 64B requests issued to device : Each outbound cacheline granular request may need to make multiple passes through the pipeline. Each time a cacheline completes all its passes it advances line", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "Outbound TLP (transaction layer packet) requests issued : To device", + "EventCode": "0xd1", + "EventName": "UNC_IIO_OUTBOUND_TLP_REQS_ISSUED.TO_IO", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Outbound TLP (transaction layer packet) requests issued : To device : Each time an outbound completes all its passes it advances the pointer", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "PWT occupancy. Does not include 9th bit of occupancy (will undercount if PWT is greater than 255 per cycle).", + "EventCode": "0x42", + "EventName": "UNC_IIO_PWT_OCCUPANCY", + "PerPkg": "1", + "PortMask": "0x0000", + "PublicDescription": "PWT occupancy : Indicates how many page walks are outstanding at any point in time.", + "UMask": "0xff", + "Unit": "IIO" + }, + { + "BriefDescription": "Request Ownership : PCIe Request complete", + "EventCode": "0x91", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CL_CMPL.DATA", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Request Ownership : PCIe Request complete : Only for posted requests : Each PCIe request is broken down into a series of cacheline granular requests and each cacheline size request may need to make multiple passes through the pipeline (e.g. for posted interrupts or multi-cast). Each time a single PCIe request completes all its cacheline granular requests, it advances pointer.", + "UMask": "0x70ff020", + "Unit": "IIO" + }, + { + "BriefDescription": "Request Ownership : Writing line", + "EventCode": "0x91", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CL_CMPL.FINAL_RD_WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Request Ownership : Writing line : Only for posted requests : Only for posted requests", + "UMask": "0x70ff008", + "Unit": "IIO" + }, + { + "BriefDescription": "Request Ownership : Issuing final read or write of line", + "EventCode": "0x91", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CL_CMPL.REQ_OWN", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Request Ownership : Issuing final read or write of line : Only for posted requests", + "UMask": "0x70ff004", + "Unit": "IIO" + }, + { + "BriefDescription": "Request Ownership : Passing data to be written", + "EventCode": "0x91", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CL_CMPL.WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Request Ownership : Passing data to be written : Only for posted requests : Only for posted requests", + "UMask": "0x70ff010", + "Unit": "IIO" + }, + { + "BriefDescription": "Processing response from IOMMU : Passing data to be written", + "EventCode": "0x92", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CMPL.FINAL_RD_WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Processing response from IOMMU : Passing data to be written : Only for posted requests", + "UMask": "0x70ff008", + "Unit": "IIO" + }, + { + "BriefDescription": "Processing response from IOMMU : Issuing final read or write of line", + "EventCode": "0x92", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CMPL.IOMMU_HIT", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "UMask": "0x70ff002", + "Unit": "IIO" + }, + { + "BriefDescription": "Processing response from IOMMU : Request Ownership", + "EventCode": "0x92", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CMPL.IOMMU_REQ", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Processing response from IOMMU : Request Ownership : Only for posted requests", + "UMask": "0x70ff001", + "Unit": "IIO" + }, + { + "BriefDescription": "Processing response from IOMMU : Writing line", + "EventCode": "0x92", + "EventName": "UNC_IIO_REQ_FROM_PCIE_CMPL.REQ_OWN", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "Processing response from IOMMU : Writing line : Only for posted requests", + "UMask": "0x70ff004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Request - pass complete : Passing data to be written", + "EventCode": "0x90", + "EventName": "UNC_IIO_REQ_FROM_PCIE_PASS_CMPL.DATA", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "PCIe Request - pass complete : Passing data to be written : Each PCIe request is broken down into a series of cacheline granular requests and each cacheline size request may need to make multiple passes through the pipeline (e.g. for posted interrupts or multi-cast). Each time a cacheline completes a single pass (e.g. posts a write to single multi-cast target) it advances state : Only for posted requests", + "UMask": "0x70ff020", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Request - pass complete : Issuing final read or write of line", + "EventCode": "0x90", + "EventName": "UNC_IIO_REQ_FROM_PCIE_PASS_CMPL.FINAL_RD_WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "PCIe Request - pass complete : Issuing final read or write of line : Each PCIe request is broken down into a series of cacheline granular requests and each cacheline size request may need to make multiple passes through the pipeline (e.g. for posted interrupts or multi-cast). Each time a cacheline completes a single pass (e.g. posts a write to single multi-cast target) it advances state", + "UMask": "0x8", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Request - pass complete : Request Ownership", + "EventCode": "0x90", + "EventName": "UNC_IIO_REQ_FROM_PCIE_PASS_CMPL.REQ_OWN", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "PCIe Request - pass complete : Request Ownership : Each PCIe request is broken down into a series of cacheline granular requests and each cacheline size request may need to make multiple passes through the pipeline (e.g. for posted interrupts or multi-cast). Each time a cacheline completes a single pass (e.g. posts a write to single multi-cast target) it advances state : Only for posted requests", + "UMask": "0x70ff004", + "Unit": "IIO" + }, + { + "BriefDescription": "PCIe Request - pass complete : Writing line", + "EventCode": "0x90", + "EventName": "UNC_IIO_REQ_FROM_PCIE_PASS_CMPL.WR", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x00FF", + "PublicDescription": "PCIe Request - pass complete : Writing line : Each PCIe request is broken down into a series of cacheline granular requests and each cacheline size request may need to make multiple passes through the pipeline (e.g. for posted interrupts or multi-cast). Each time a cacheline completes a single pass (e.g. posts a write to single multi-cast target) it advances state : Only for posted requests", + "UMask": "0x70ff010", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part0", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part1", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part2", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by the CPU to IIO Part3", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested by the CPU : Core reading from Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part0 by the CPU", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part1 by the CPU", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part2 by the CPU", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made to IIO Part3 by the CPU", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Card's MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested by the CPU : Core writing to Cards MMIO space : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x7001002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x7002002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 2", + "UMask": "0x7004002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x7008002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x16 card plugged in to Lane 4/5/6/7, Or x8 card plugged in to Lane 4/5, Or x4 card is plugged in to slot 4", + "UMask": "0x7010002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 5", + "UMask": "0x7020002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x8 card plugged in to Lane 6/7, Or x4 card is plugged in to slot 6", + "UMask": "0x7040002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card.", + "EventCode": "0xc1", + "EventName": "UNC_IIO_TXN_REQ_BY_CPU.PEER_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested by the CPU : Another card (different IIO stack) writing to this card. : Also known as Outbound. Number of requests initiated by the main die, including reads and writes. : x4 card is plugged in to slot 7", + "UMask": "0x7080002", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 2", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 4/5/6/7, Or x8 card plugged in to Lane 4/5, Or x4 card is plugged in to slot 4", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 5", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 6/7, Or x4 card is plugged in to slot 6", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.CMPD.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested of the CPU : CmpD - device sending completion to CPU request : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 7", + "UMask": "0x80", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part0 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part1 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part2 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Read request for up to a 64 byte transaction is made by IIO Part3 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card reading from DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_READ.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested of the CPU : Card reading from DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x4", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part0 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part1 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part2 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Write request of up to a 64 byte transaction is made by IIO Part3 to Memory", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to stack, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 1", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to DRAM", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.MEM_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to DRAM : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x1", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART0", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0001", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 0/1/2/3, Or x8 card plugged in to Lane 0/1, Or x4 card is plugged in to slot 0", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART1", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0002", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 1", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART2", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0004", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 2/3, Or x4 card is plugged in to slot 2", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART3", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0008", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 3", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART4", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0010", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x16 card plugged in to Lane 4/5/6/7, Or x8 card plugged in to Lane 4/5, Or x4 card is plugged in to slot 4", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART5", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0020", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 5", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART6", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0040", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x8 card plugged in to Lane 6/7, Or x4 card is plugged in to slot 6", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack)", + "EventCode": "0x84", + "EventName": "UNC_IIO_TXN_REQ_OF_CPU.PEER_WRITE.PART7", + "FCMask": "0x07", + "PerPkg": "1", + "PortMask": "0x0080", + "PublicDescription": "Number Transactions requested of the CPU : Card writing to another Card (same or different stack) : Also known as Inbound. Number of 64B cache line requests initiated by the Card, including reads and writes. : x4 card is plugged in to slot 7", + "UMask": "0x2", + "Unit": "IIO" + }, + { + "BriefDescription": "M2P Clockticks", + "EventCode": "0x01", + "EventName": "UNC_M2P_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of M2P clock cycles while the event is enabled", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "CMS Clockticks", + "EventCode": "0xc0", + "EventName": "UNC_M2P_CMS_CLOCKTICKS", + "PerPkg": "1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Down", + "EventCode": "0xba", + "EventName": "UNC_M2P_EGRESS_ORDERING.IV_SNOOPGO_DN", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Down : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Up", + "EventCode": "0xba", + "EventName": "UNC_M2P_EGRESS_ORDERING.IV_SNOOPGO_UP", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Up : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credit Acquired : DRS", + "EventCode": "0x33", + "EventName": "UNC_M2P_IIO_CREDITS_ACQUIRED.DRS_0", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credit Acquired : DRS : Counts the number of credits that are acquired in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the DRS message class.", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credit Acquired : DRS", + "EventCode": "0x33", + "EventName": "UNC_M2P_IIO_CREDITS_ACQUIRED.DRS_1", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credit Acquired : DRS : Counts the number of credits that are acquired in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the DRS message class.", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credit Acquired : NCB", + "EventCode": "0x33", + "EventName": "UNC_M2P_IIO_CREDITS_ACQUIRED.NCB_0", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credit Acquired : NCB : Counts the number of credits that are acquired in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the NCB message class.", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credit Acquired : NCB", + "EventCode": "0x33", + "EventName": "UNC_M2P_IIO_CREDITS_ACQUIRED.NCB_1", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credit Acquired : NCB : Counts the number of credits that are acquired in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the NCB message class.", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credit Acquired : NCS", + "EventCode": "0x33", + "EventName": "UNC_M2P_IIO_CREDITS_ACQUIRED.NCS_0", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credit Acquired : NCS : Counts the number of credits that are acquired in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the NCS message class.", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credit Acquired : NCS", + "EventCode": "0x33", + "EventName": "UNC_M2P_IIO_CREDITS_ACQUIRED.NCS_1", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credit Acquired : NCS : Counts the number of credits that are acquired in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credit for transfer through CMS Port 0s to the IIO for the NCS message class.", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Failed to Acquire a Credit : DRS", + "EventCode": "0x34", + "EventName": "UNC_M2P_IIO_CREDITS_REJECT.DRS", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Failed to Acquire a Credit : DRS : Counts the number of times that a request pending in the BL Ingress attempted to acquire either a NCB or NCS credit to transmit into the IIO, but was rejected because no credits were available. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits to the IIO for the DRS message class.", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Failed to Acquire a Credit : NCB", + "EventCode": "0x34", + "EventName": "UNC_M2P_IIO_CREDITS_REJECT.NCB", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Failed to Acquire a Credit : NCB : Counts the number of times that a request pending in the BL Ingress attempted to acquire either a NCB or NCS credit to transmit into the IIO, but was rejected because no credits were available. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits to the IIO for the NCB message class.", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Failed to Acquire a Credit : NCS", + "EventCode": "0x34", + "EventName": "UNC_M2P_IIO_CREDITS_REJECT.NCS", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Failed to Acquire a Credit : NCS : Counts the number of times that a request pending in the BL Ingress attempted to acquire either a NCB or NCS credit to transmit into the IIO, but was rejected because no credits were available. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits to the IIO for the NCS message class.", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credits in Use : DRS to CMS Port 0", + "EventCode": "0x32", + "EventName": "UNC_M2P_IIO_CREDITS_USED.DRS_0", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credits in Use : DRS to CMS Port 0 : Counts the number of cycles when one or more credits in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the DRS message class.", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credits in Use : DRS to CMS Port 1", + "EventCode": "0x32", + "EventName": "UNC_M2P_IIO_CREDITS_USED.DRS_1", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credits in Use : DRS to CMS Port 1 : Counts the number of cycles when one or more credits in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the DRS message class.", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credits in Use : NCB to CMS Port 0", + "EventCode": "0x32", + "EventName": "UNC_M2P_IIO_CREDITS_USED.NCB_0", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credits in Use : NCB to CMS Port 0 : Counts the number of cycles when one or more credits in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the NCB message class.", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credits in Use : NCB to CMS Port 1", + "EventCode": "0x32", + "EventName": "UNC_M2P_IIO_CREDITS_USED.NCB_1", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credits in Use : NCB to CMS Port 1 : Counts the number of cycles when one or more credits in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the NCB message class.", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credits in Use : NCS to CMS Port 0", + "EventCode": "0x32", + "EventName": "UNC_M2P_IIO_CREDITS_USED.NCS_0", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credits in Use : NCS to CMS Port 0 : Counts the number of cycles when one or more credits in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credits for transfer through CMS Port 0 to the IIO for the NCS message class.", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "M2PCIe IIO Credits in Use : NCS to CMS Port 1", + "EventCode": "0x32", + "EventName": "UNC_M2P_IIO_CREDITS_USED.NCS_1", + "PerPkg": "1", + "PublicDescription": "M2PCIe IIO Credits in Use : NCS to CMS Port 1 : Counts the number of cycles when one or more credits in the M2PCIe agent for sending transactions into the IIO on either NCB or NCS are in use. Transactions from the BL ring going into the IIO Agent must first acquire a credit. These credits are for either the NCB or NCS message classes. NCB, or non-coherent bypass messages are used to transmit data without coherency (and are common). NCS is used for reads to PCIe (and should be used sparingly). : Credit for transfer through CMS Port 0s to the IIO for the NCS message class.", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF0 - NCB", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF0_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF0 - NCS", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF0_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF1 - NCB", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF1_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF1 - NCS", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF1_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF2 - NCB", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF2_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF2 - NCS", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF2_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF3 - NCB", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF3_NCB", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 0 : M2IOSF3 - NCS", + "EventCode": "0x46", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_0.M2IOSF3_NCS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 1 : M2IOSF4 - NCB", + "EventCode": "0x47", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_1.M2IOSF4_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 1 : M2IOSF4 - NCS", + "EventCode": "0x47", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_1.M2IOSF4_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 1 : M2IOSF5 - NCB", + "EventCode": "0x47", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_1.M2IOSF5_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Dedicated P2P Credit Taken - 1 : M2IOSF5 - NCS", + "EventCode": "0x47", + "EventName": "UNC_M2P_LOCAL_DED_P2P_CRD_TAKEN_1.M2IOSF5_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF0 - NCB", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF0_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF0 - NCS", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF0_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF1 - NCB", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF1_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF1 - NCS", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF1_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF2 - NCB", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF2_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF2 - NCS", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF2_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF3 - NCB", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF3_NCB", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 0 : M2IOSF3 - NCS", + "EventCode": "0x19", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_0.MS2IOSF3_NCS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 1 : M2IOSF4 - NCB", + "EventCode": "0x1a", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_1.MS2IOSF4_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 1 : M2IOSF4 - NCS", + "EventCode": "0x1a", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_1.MS2IOSF4_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 1 : M2IOSF5 - NCB", + "EventCode": "0x1a", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_1.MS2IOSF5_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Dedicated Credits Returned - 1 : M2IOSF5 - NCS", + "EventCode": "0x1a", + "EventName": "UNC_M2P_LOCAL_P2P_DED_RETURNED_1.MS2IOSF5_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Shared Credits Returned : Agent0", + "EventCode": "0x17", + "EventName": "UNC_M2P_LOCAL_P2P_SHAR_RETURNED.AGENT_0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Shared Credits Returned : Agent1", + "EventCode": "0x17", + "EventName": "UNC_M2P_LOCAL_P2P_SHAR_RETURNED.AGENT_1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local P2P Shared Credits Returned : Agent2", + "EventCode": "0x17", + "EventName": "UNC_M2P_LOCAL_P2P_SHAR_RETURNED.AGENT_2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Returned to credit ring : Agent0", + "EventCode": "0x44", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_RETURNED.AGENT_0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Returned to credit ring : Agent1", + "EventCode": "0x44", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_RETURNED.AGENT_1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Returned to credit ring : Agent2", + "EventCode": "0x44", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_RETURNED.AGENT_2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Returned to credit ring : Agent3", + "EventCode": "0x44", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_RETURNED.AGENT_3", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Returned to credit ring : Agent4", + "EventCode": "0x44", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_RETURNED.AGENT_4", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Returned to credit ring : Agent5", + "EventCode": "0x44", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_RETURNED.AGENT_5", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF0 - NCB", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF0_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF0 - NCS", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF0_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF1 - NCB", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF1_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF1 - NCS", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF1_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF2 - NCB", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF2_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF2 - NCS", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF2_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF3 - NCB", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF3_NCB", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 0 : M2IOSF3 - NCS", + "EventCode": "0x40", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_0.M2IOSF3_NCS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 1 : M2IOSF4 - NCB", + "EventCode": "0x41", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_1.M2IOSF4_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 1 : M2IOSF4 - NCS", + "EventCode": "0x41", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_1.M2IOSF4_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 1 : M2IOSF5 - NCB", + "EventCode": "0x41", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_1.M2IOSF5_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Local Shared P2P Credit Taken - 1 : M2IOSF5 - NCS", + "EventCode": "0x41", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_TAKEN_1.M2IOSF5_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF0 - NCB", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF0_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF0 - NCS", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF0_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF1 - NCB", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF1_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF1 - NCS", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF1_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF2 - NCB", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF2_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF2 - NCS", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF2_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF3 - NCB", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF3_NCB", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 0 : M2IOSF3 - NCS", + "EventCode": "0x4a", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_0.M2IOSF3_NCS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 1 : M2IOSF4 - NCB", + "EventCode": "0x4b", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_1.M2IOSF4_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 1 : M2IOSF4 - NCS", + "EventCode": "0x4b", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_1.M2IOSF4_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 1 : M2IOSF5 - NCB", + "EventCode": "0x4b", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_1.M2IOSF5_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Local Shared P2P Credit - 1 : M2IOSF5 - NCS", + "EventCode": "0x4b", + "EventName": "UNC_M2P_LOCAL_SHAR_P2P_CRD_WAIT_1.M2IOSF5_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "P2P Credit Occupancy : All", + "EventCode": "0x14", + "EventName": "UNC_M2P_P2P_CRD_OCCUPANCY.ALL", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "P2P Credit Occupancy : Local NCB", + "EventCode": "0x14", + "EventName": "UNC_M2P_P2P_CRD_OCCUPANCY.LOCAL_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "P2P Credit Occupancy : Local NCS", + "EventCode": "0x14", + "EventName": "UNC_M2P_P2P_CRD_OCCUPANCY.LOCAL_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "P2P Credit Occupancy : Remote NCB", + "EventCode": "0x14", + "EventName": "UNC_M2P_P2P_CRD_OCCUPANCY.REMOTE_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "P2P Credit Occupancy : Remote NCS", + "EventCode": "0x14", + "EventName": "UNC_M2P_P2P_CRD_OCCUPANCY.REMOTE_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Dedicated Credits Received : All", + "EventCode": "0x16", + "EventName": "UNC_M2P_P2P_DED_RECEIVED.ALL", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Dedicated Credits Received : Local NCB", + "EventCode": "0x16", + "EventName": "UNC_M2P_P2P_DED_RECEIVED.LOCAL_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Dedicated Credits Received : Local NCS", + "EventCode": "0x16", + "EventName": "UNC_M2P_P2P_DED_RECEIVED.LOCAL_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Dedicated Credits Received : Remote NCB", + "EventCode": "0x16", + "EventName": "UNC_M2P_P2P_DED_RECEIVED.REMOTE_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Dedicated Credits Received : Remote NCS", + "EventCode": "0x16", + "EventName": "UNC_M2P_P2P_DED_RECEIVED.REMOTE_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Shared Credits Received : All", + "EventCode": "0x15", + "EventName": "UNC_M2P_P2P_SHAR_RECEIVED.ALL", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Shared Credits Received : Local NCB", + "EventCode": "0x15", + "EventName": "UNC_M2P_P2P_SHAR_RECEIVED.LOCAL_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Shared Credits Received : Local NCS", + "EventCode": "0x15", + "EventName": "UNC_M2P_P2P_SHAR_RECEIVED.LOCAL_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Shared Credits Received : Remote NCB", + "EventCode": "0x15", + "EventName": "UNC_M2P_P2P_SHAR_RECEIVED.REMOTE_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Shared Credits Received : Remote NCS", + "EventCode": "0x15", + "EventName": "UNC_M2P_P2P_SHAR_RECEIVED.REMOTE_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 0 : UPI0 - DRS", + "EventCode": "0x48", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_0.UPI0_DRS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 0 : UPI0 - NCB", + "EventCode": "0x48", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_0.UPI0_NCB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 0 : UPI0 - NCS", + "EventCode": "0x48", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_0.UPI0_NCS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 0 : UPI1 - DRS", + "EventCode": "0x48", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_0.UPI1_DRS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 0 : UPI1 - NCB", + "EventCode": "0x48", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_0.UPI1_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 0 : UPI1 - NCS", + "EventCode": "0x48", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_0.UPI1_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 1 : UPI2 - DRS", + "EventCode": "0x49", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_1.UPI2_DRS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 1 : UPI2 - NCB", + "EventCode": "0x49", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_1.UPI2_NCB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Dedicated P2P Credit Taken - 1 : UPI2 - NCS", + "EventCode": "0x49", + "EventName": "UNC_M2P_REMOTE_DED_P2P_CRD_TAKEN_1.UPI2_NCS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Dedicated Credits Returned : UPI0 - NCB", + "EventCode": "0x1b", + "EventName": "UNC_M2P_REMOTE_P2P_DED_RETURNED.UPI0_NCB", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Dedicated Credits Returned : UPI0 - NCS", + "EventCode": "0x1b", + "EventName": "UNC_M2P_REMOTE_P2P_DED_RETURNED.UPI0_NCS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Dedicated Credits Returned : UPI1 - NCB", + "EventCode": "0x1b", + "EventName": "UNC_M2P_REMOTE_P2P_DED_RETURNED.UPI1_NCB", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Dedicated Credits Returned : UPI1 - NCS", + "EventCode": "0x1b", + "EventName": "UNC_M2P_REMOTE_P2P_DED_RETURNED.UPI1_NCS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Dedicated Credits Returned : UPI2 - NCB", + "EventCode": "0x1b", + "EventName": "UNC_M2P_REMOTE_P2P_DED_RETURNED.UPI2_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Dedicated Credits Returned : UPI2 - NCS", + "EventCode": "0x1b", + "EventName": "UNC_M2P_REMOTE_P2P_DED_RETURNED.UPI2_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Shared Credits Returned : Agent0", + "EventCode": "0x18", + "EventName": "UNC_M2P_REMOTE_P2P_SHAR_RETURNED.AGENT_0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Shared Credits Returned : Agent1", + "EventCode": "0x18", + "EventName": "UNC_M2P_REMOTE_P2P_SHAR_RETURNED.AGENT_1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote P2P Shared Credits Returned : Agent2", + "EventCode": "0x18", + "EventName": "UNC_M2P_REMOTE_P2P_SHAR_RETURNED.AGENT_2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Returned to credit ring : Agent0", + "EventCode": "0x45", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_RETURNED.AGENT_0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Returned to credit ring : Agent1", + "EventCode": "0x45", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_RETURNED.AGENT_1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Returned to credit ring : Agent2", + "EventCode": "0x45", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_RETURNED.AGENT_2", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 0 : UPI0 - DRS", + "EventCode": "0x42", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_0.UPI0_DRS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 0 : UPI0 - NCB", + "EventCode": "0x42", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_0.UPI0_NCB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 0 : UPI0 - NCS", + "EventCode": "0x42", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_0.UPI0_NCS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 0 : UPI1 - DRS", + "EventCode": "0x42", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_0.UPI1_DRS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 0 : UPI1 - NCB", + "EventCode": "0x42", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_0.UPI1_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 0 : UPI1 - NCS", + "EventCode": "0x42", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_0.UPI1_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 1 : UPI2 - DRS", + "EventCode": "0x43", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_1.UPI2_DRS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 1 : UPI2 - NCB", + "EventCode": "0x43", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_1.UPI2_NCB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Remote Shared P2P Credit Taken - 1 : UPI2 - NCS", + "EventCode": "0x43", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_TAKEN_1.UPI2_NCS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 0 : UPI0 - DRS", + "EventCode": "0x4c", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_0.UPI0_DRS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 0 : UPI0 - NCB", + "EventCode": "0x4c", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_0.UPI0_NCB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 0 : UPI0 - NCS", + "EventCode": "0x4c", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_0.UPI0_NCS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 0 : UPI1 - DRS", + "EventCode": "0x4c", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_0.UPI1_DRS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 0 : UPI1 - NCB", + "EventCode": "0x4c", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_0.UPI1_NCB", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 0 : UPI1 - NCS", + "EventCode": "0x4c", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_0.UPI1_NCS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 1 : UPI2 - DRS", + "EventCode": "0x4d", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_1.UPI2_DRS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 1 : UPI2 - NCB", + "EventCode": "0x4d", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_1.UPI2_NCB", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Waiting on Remote Shared P2P Credit - 1 : UPI2 - NCS", + "EventCode": "0x4d", + "EventName": "UNC_M2P_REMOTE_SHAR_P2P_CRD_WAIT_1.UPI2_NCS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.ALL", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.CHA_IDI", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.CHA_NCB", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.CHA_NCS", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.IIO_NCB", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.IIO_NCS", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x40", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.UPI_NCB", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Cycles Not Empty", + "EventCode": "0x10", + "EventName": "UNC_M2P_RxC_CYCLES_NE.UPI_NCS", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Cycles Not Empty : Counts the number of cycles when the M2PCIe Ingress is not empty.", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.ALL", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.CHA_IDI", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.CHA_NCB", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.CHA_NCS", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x4", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.IIO_NCB", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x20", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.IIO_NCS", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x40", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.UPI_NCB", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Ingress (from CMS) Queue Inserts", + "EventCode": "0x11", + "EventName": "UNC_M2P_RxC_INSERTS.UPI_NCS", + "PerPkg": "1", + "PublicDescription": "Ingress (from CMS) Queue Inserts : Counts the number of entries inserted into the M2PCIe Ingress Queue. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue latency.", + "UMask": "0x10", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "UNC_M2P_TxC_CREDITS.PMM", + "EventCode": "0x2d", + "EventName": "UNC_M2P_TxC_CREDITS.PMM", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "UNC_M2P_TxC_CREDITS.PRQ", + "EventCode": "0x2d", + "EventName": "UNC_M2P_TxC_CREDITS.PRQ", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Egress (to CMS) Cycles Full", + "EventCode": "0x25", + "EventName": "UNC_M2P_TxC_CYCLES_FULL.PMM_BLOCK_0", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Egress (to CMS) Cycles Full : Counts the number of cycles when the M2PCIe Egress is full. This tracks messages for one of the two CMS ports that are used by the M2PCIe agent.", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Egress (to CMS) Cycles Full", + "EventCode": "0x25", + "EventName": "UNC_M2P_TxC_CYCLES_FULL.PMM_BLOCK_1", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Egress (to CMS) Cycles Full : Counts the number of cycles when the M2PCIe Egress is full. This tracks messages for one of the two CMS ports that are used by the M2PCIe agent.", + "UMask": "0x8", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Egress (to CMS) Cycles Not Empty", + "EventCode": "0x23", + "EventName": "UNC_M2P_TxC_CYCLES_NE.PMM_DISTRESS_0", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Egress (to CMS) Cycles Not Empty : Counts the number of cycles when the M2PCIe Egress is not empty. This tracks messages for one of the two CMS ports that are used by the M2PCIe agent. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple egress buffers can be tracked at a given time using multiple counters.", + "UMask": "0x80", + "Unit": "M2PCIe" + }, + { + "BriefDescription": "Egress (to CMS) Cycles Not Empty", + "EventCode": "0x23", + "EventName": "UNC_M2P_TxC_CYCLES_NE.PMM_DISTRESS_1", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Egress (to CMS) Cycles Not Empty : Counts the number of cycles when the M2PCIe Egress is not empty. This tracks messages for one of the two CMS ports that are used by the M2PCIe agent. This can be used in conjunction with the M2PCIe Ingress Occupancy Accumulator event in order to calculate average queue occupancy. Multiple egress buffers can be tracked at a given time using multiple counters.", + "UMask": "0x8", + "Unit": "M2PCIe" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-memory.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-memory.json new file mode 100644 index 000000000000..3ff9e9b722c8 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-memory.json @@ -0,0 +1,3308 @@ +[ + { + "BriefDescription": "Cycles - at UCLK", + "EventCode": "0x01", + "EventName": "UNC_M2HBM_CLOCKTICKS", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "CMS Clockticks", + "EventCode": "0xc0", + "EventName": "UNC_M2HBM_CMS_CLOCKTICKS", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Cycles when direct to core mode (which bypasses the CHA) was disabled", + "EventCode": "0x17", + "EventName": "UNC_M2HBM_DIRECT2CORE_NOT_TAKEN_DIRSTATE", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Cycles when direct to core mode, which bypasses the CHA, was disabled : Non Cisgress", + "EventCode": "0x17", + "EventName": "UNC_M2HBM_DIRECT2CORE_NOT_TAKEN_DIRSTATE.NON_CISGRESS", + "PerPkg": "1", + "PublicDescription": "Counts the number of time non cisgress D2C was not honoured by egress due to directory state constraints", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Counts the time when FM didn't do d2c for fill reads (cross tile case)", + "EventCode": "0x4a", + "EventName": "UNC_M2HBM_DIRECT2CORE_NOT_TAKEN_NOTFORKED", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number of reads in which direct to core transaction were overridden", + "EventCode": "0x18", + "EventName": "UNC_M2HBM_DIRECT2CORE_TXN_OVERRIDE", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number of reads in which direct to core transaction was overridden : Cisgress", + "EventCode": "0x18", + "EventName": "UNC_M2HBM_DIRECT2CORE_TXN_OVERRIDE.CISGRESS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number of reads in which direct to Intel UPI transactions were overridden", + "EventCode": "0x1b", + "EventName": "UNC_M2HBM_DIRECT2UPI_NOT_TAKEN_CREDITS", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Cycles when direct to Intel UPI was disabled", + "EventCode": "0x1a", + "EventName": "UNC_M2HBM_DIRECT2UPI_NOT_TAKEN_DIRSTATE", + "PerPkg": "1", + "UMask": "0x7", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Cisgress D2U Ignored", + "EventCode": "0x1A", + "EventName": "UNC_M2HBM_DIRECT2UPI_NOT_TAKEN_DIRSTATE.CISGRESS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts cisgress d2K that was not honored due to directory constraints", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Egress Ignored D2U", + "EventCode": "0x1A", + "EventName": "UNC_M2HBM_DIRECT2UPI_NOT_TAKEN_DIRSTATE.EGRESS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of time D2K was not honoured by egress due to directory state constraints", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Cycles when Direct2UPI was Disabled : Non Cisgress D2U Ignored", + "EventCode": "0x1A", + "EventName": "UNC_M2HBM_DIRECT2UPI_NOT_TAKEN_DIRSTATE.NON_CISGRESS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts non cisgress d2K that was not honored due to directory constraints", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number of reads that a message sent direct2 Intel UPI was overridden", + "EventCode": "0x1c", + "EventName": "UNC_M2HBM_DIRECT2UPI_TXN_OVERRIDE", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number of times a direct to UPI transaction was overridden.", + "EventCode": "0x1c", + "EventName": "UNC_M2HBM_DIRECT2UPI_TXN_OVERRIDE.CISGRESS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in A State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.CLEAN_A", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in I State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.CLEAN_I", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in L State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.CLEAN_P", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On NonDirty Line in S State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.CLEAN_S", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in A State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.DIRTY_A", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in I State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.DIRTY_I", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in L State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.DIRTY_P", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Hit : On Dirty Line in S State", + "EventCode": "0x1d", + "EventName": "UNC_M2HBM_DIRECTORY_HIT.DIRTY_S", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookups (any state found)", + "EventCode": "0x20", + "EventName": "UNC_M2HBM_DIRECTORY_LOOKUP.ANY", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with any directory to non persistent memory", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookups (cacheline found in A state)", + "EventCode": "0x20", + "EventName": "UNC_M2HBM_DIRECTORY_LOOKUP.STATE_A", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with directory A to non persistent memory", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookup (cacheline found in I state)", + "EventCode": "0x20", + "EventName": "UNC_M2HBM_DIRECTORY_LOOKUP.STATE_I", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with directory I to non persistent memory", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory lookup (cacheline found in S state)", + "EventCode": "0x20", + "EventName": "UNC_M2HBM_DIRECTORY_LOOKUP.STATE_S", + "PerPkg": "1", + "PublicDescription": "Counts the number of hit data returns to egress with directory S to non persistent memory", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in A State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.CLEAN_A", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in I State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.CLEAN_I", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in L State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.CLEAN_P", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On NonDirty Line in S State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.CLEAN_S", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in A State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.DIRTY_A", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in I State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.DIRTY_I", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in L State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.DIRTY_P", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Directory Miss : On Dirty Line in S State", + "EventCode": "0x1e", + "EventName": "UNC_M2HBM_DIRECTORY_MISS.DIRTY_S", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from A to I", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.A2I", + "PerPkg": "1", + "UMask": "0x320", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from A to S", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.A2S", + "PerPkg": "1", + "UMask": "0x340", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from/to Any state", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.ANY", + "PerPkg": "1", + "UMask": "0x301", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.A_TO_I_HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from A to I to non persistent memory", + "UMask": "0x120", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.A_TO_I_MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from A to I to non persistent memory", + "UMask": "0x220", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.A_TO_S_HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from A to S to non persistent memory", + "UMask": "0x140", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.A_TO_S_MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from A to S to non persistent memory", + "UMask": "0x240", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts any 1lm or 2lm hit data return that would result in directory update to non persistent memory", + "UMask": "0x101", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from I to A", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.I2A", + "PerPkg": "1", + "UMask": "0x304", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from I to S", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.I2S", + "PerPkg": "1", + "UMask": "0x302", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.I_TO_A_HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from I to A to non persistent memory", + "UMask": "0x104", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.I_TO_A_MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from I to A to non persistent memory", + "UMask": "0x204", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.I_TO_S_HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from I to S to non persistent memory", + "UMask": "0x102", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.I_TO_S_MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from I to S to non persistent memory", + "UMask": "0x202", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts any 2lm miss data return that would result in directory update to non persistent memory", + "UMask": "0x201", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from S to A", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.S2A", + "PerPkg": "1", + "UMask": "0x310", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory update from S to I", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.S2I", + "PerPkg": "1", + "UMask": "0x308", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.S_TO_A_HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from S to A to non persistent memory", + "UMask": "0x110", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.S_TO_A_MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from S to A to non persistent memory", + "UMask": "0x210", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.S_TO_I_HIT_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 1lm or 2lm hit data returns that would result in directory update from S to I to non persistent memory", + "UMask": "0x108", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Multi-socket cacheline Directory Updates", + "EventCode": "0x21", + "EventName": "UNC_M2HBM_DIRECTORY_UPDATE.S_TO_I_MISS_NON_PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts 2lm miss data returns that would result in directory update from S to I to non persistent memory", + "UMask": "0x208", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on AkAd cmp message", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.AD", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on any packet type", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.ALL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on Bl Cmp message", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.BL_CMP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on NM fill write message", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.CROSSTILE_NMWR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on D2Cha message", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.D2CHA", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on D2c message", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.D2CORE", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count distress signalled on D2k message", + "EventCode": "0x67", + "EventName": "UNC_M2HBM_DISTRESS.D2UPI", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Down", + "EventCode": "0xba", + "EventName": "UNC_M2HBM_EGRESS_ORDERING.IV_SNOOPGO_DN", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Down : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x80000004", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Egress Blocking due to Ordering requirements : Up", + "EventCode": "0xba", + "EventName": "UNC_M2HBM_EGRESS_ORDERING.IV_SNOOPGO_UP", + "PerPkg": "1", + "PublicDescription": "Egress Blocking due to Ordering requirements : Up : Counts number of cycles IV was blocked in the TGR Egress due to SNP/GO Ordering requirements", + "UMask": "0x80000001", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Count when Starve Glocab counter is at 7", + "EventCode": "0x44", + "EventName": "UNC_M2HBM_IGR_STARVE_WINNER.MASK7", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x80", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Reads to iMC issued", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.ALL", + "PerPkg": "1", + "UMask": "0x304", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH0.ALL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH0.ALL", + "PerPkg": "1", + "UMask": "0x104", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH0.NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH0.NORMAL", + "PerPkg": "1", + "UMask": "0x101", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH0_ALL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH0_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x104", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH0_FROM_TGR", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH0_FROM_TGR", + "PerPkg": "1", + "UMask": "0x140", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Critical Priority - Ch0", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH0_ISOCH", + "PerPkg": "1", + "UMask": "0x102", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH0_NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH0_NORMAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x101", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH1.ALL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH1.ALL", + "PerPkg": "1", + "UMask": "0x204", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH1.NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH1.NORMAL", + "PerPkg": "1", + "UMask": "0x201", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH1_ALL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH1_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x204", + "Unit": "M2HBM" + }, + { + "BriefDescription": "From TGR - Ch1", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH1_FROM_TGR", + "PerPkg": "1", + "UMask": "0x240", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Critical Priority - Ch1", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH1_ISOCH", + "PerPkg": "1", + "UMask": "0x202", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.CH1_NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.CH1_NORMAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x201", + "Unit": "M2HBM" + }, + { + "BriefDescription": "From TGR - All Channels", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.FROM_TGR", + "PerPkg": "1", + "UMask": "0x340", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Critical Priority - All Channels", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.ISOCH", + "PerPkg": "1", + "UMask": "0x302", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_READS.NORMAL", + "EventCode": "0x24", + "EventName": "UNC_M2HBM_IMC_READS.NORMAL", + "PerPkg": "1", + "UMask": "0x301", + "Unit": "M2HBM" + }, + { + "BriefDescription": "All Writes - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.ALL", + "PerPkg": "1", + "UMask": "0x1810", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_WRITES.CH0.ALL", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0.ALL", + "PerPkg": "1", + "UMask": "0x810", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_WRITES.CH0.FULL", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0.FULL", + "PerPkg": "1", + "UMask": "0x801", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_WRITES.CH0.PARTIAL", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0.PARTIAL", + "PerPkg": "1", + "UMask": "0x802", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_WRITES.CH0_ALL", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x810", + "Unit": "M2HBM" + }, + { + "BriefDescription": "From TGR - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_FROM_TGR", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_WRITES.CH0_FULL", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_FULL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x801", + "Unit": "M2HBM" + }, + { + "BriefDescription": "ISOCH Full Line - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_FULL_ISOCH", + "PerPkg": "1", + "UMask": "0x804", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Non-Inclusive - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_NI", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Non-Inclusive Miss - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_NI_MISS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_IMC_WRITES.CH0_PARTIAL", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_PARTIAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x802", + "Unit": "M2HBM" + }, + { + "BriefDescription": "ISOCH Partial - Ch0", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH0_PARTIAL_ISOCH", + "PerPkg": "1", + "UMask": "0x808", + "Unit": "M2HBM" + }, + { + "BriefDescription": "All Writes - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1.ALL", + "PerPkg": "1", + "UMask": "0x1010", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Full Line Non-ISOCH - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1.FULL", + "PerPkg": "1", + "UMask": "0x1001", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Partial Non-ISOCH - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1.PARTIAL", + "PerPkg": "1", + "UMask": "0x1002", + "Unit": "M2HBM" + }, + { + "BriefDescription": "All Writes - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_ALL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1010", + "Unit": "M2HBM" + }, + { + "BriefDescription": "From TGR - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_FROM_TGR", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Full Line Non-ISOCH - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_FULL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1001", + "Unit": "M2HBM" + }, + { + "BriefDescription": "ISOCH Full Line - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_FULL_ISOCH", + "PerPkg": "1", + "UMask": "0x1004", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Non-Inclusive - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_NI", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Non-Inclusive Miss - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_NI_MISS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Partial Non-ISOCH - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_PARTIAL", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1002", + "Unit": "M2HBM" + }, + { + "BriefDescription": "ISOCH Partial - Ch1", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.CH1_PARTIAL_ISOCH", + "PerPkg": "1", + "UMask": "0x1008", + "Unit": "M2HBM" + }, + { + "BriefDescription": "From TGR - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.FROM_TGR", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Full Non-ISOCH - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.FULL", + "PerPkg": "1", + "UMask": "0x1801", + "Unit": "M2HBM" + }, + { + "BriefDescription": "ISOCH Full Line - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.FULL_ISOCH", + "PerPkg": "1", + "UMask": "0x1804", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Non-Inclusive - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.NI", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Non-Inclusive Miss - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.NI_MISS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Partial Non-ISOCH - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.PARTIAL", + "PerPkg": "1", + "UMask": "0x1802", + "Unit": "M2HBM" + }, + { + "BriefDescription": "ISOCH Partial - All Channels", + "EventCode": "0x25", + "EventName": "UNC_M2HBM_IMC_WRITES.PARTIAL_ISOCH", + "PerPkg": "1", + "UMask": "0x1808", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_PREFCAM_CIS_DROPS", + "EventCode": "0x5c", + "EventName": "UNC_M2HBM_PREFCAM_CIS_DROPS", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_DROPS.CH0_UPI", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_DROPS.CH0_XPT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_DROPS.CH1_UPI", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_DROPS.CH1_XPT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Data Prefetches Dropped : UPI - All Channels", + "EventCode": "0x58", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_DROPS.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Data Prefetches Dropped", + "EventCode": "0x58", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_DROPS.XPT_ALLCH", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "M2HBM" + }, + { + "BriefDescription": ": UPI - All Channels", + "EventCode": "0x5d", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_MERGE.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "M2HBM" + }, + { + "BriefDescription": ": XPT - All Channels", + "EventCode": "0x5d", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_MERGE.XPT_ALLCH", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Demands Not Merged with CAMed Prefetches", + "EventCode": "0x5e", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_NO_MERGE.RD_MERGED", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Demands Not Merged with CAMed Prefetches", + "EventCode": "0x5e", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_NO_MERGE.WR_MERGED", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Demands Not Merged with CAMed Prefetches", + "EventCode": "0x5e", + "EventName": "UNC_M2HBM_PREFCAM_DEMAND_NO_MERGE.WR_SQUASHED", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - Ch 0", + "EventCode": "0x56", + "EventName": "UNC_M2HBM_PREFCAM_INSERTS.CH0_UPI", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - Ch 0", + "EventCode": "0x56", + "EventName": "UNC_M2HBM_PREFCAM_INSERTS.CH0_XPT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - Ch 1", + "EventCode": "0x56", + "EventName": "UNC_M2HBM_PREFCAM_INSERTS.CH1_UPI", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - Ch 1", + "EventCode": "0x56", + "EventName": "UNC_M2HBM_PREFCAM_INSERTS.CH1_XPT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Inserts : UPI - All Channels", + "EventCode": "0x56", + "EventName": "UNC_M2HBM_PREFCAM_INSERTS.UPI_ALLCH", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Inserts : XPT - All Channels", + "EventCode": "0x56", + "EventName": "UNC_M2HBM_PREFCAM_INSERTS.XPT_ALLCH", + "PerPkg": "1", + "PublicDescription": "Prefetch CAM Inserts : XPT -All Channels", + "UMask": "0x5", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : All Channels", + "EventCode": "0x54", + "EventName": "UNC_M2HBM_PREFCAM_OCCUPANCY.ALLCH", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : Channel 0", + "EventCode": "0x54", + "EventName": "UNC_M2HBM_PREFCAM_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Prefetch CAM Occupancy : Channel 1", + "EventCode": "0x54", + "EventName": "UNC_M2HBM_PREFCAM_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "All Channels", + "EventCode": "0x5f", + "EventName": "UNC_M2HBM_PREFCAM_RESP_MISS.ALLCH", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2HBM" + }, + { + "BriefDescription": ": Channel 0", + "EventCode": "0x5f", + "EventName": "UNC_M2HBM_PREFCAM_RESP_MISS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": ": Channel 1", + "EventCode": "0x5f", + "EventName": "UNC_M2HBM_PREFCAM_RESP_MISS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_PREFCAM_RxC_DEALLOCS.1LM_POSTED", + "EventCode": "0x62", + "EventName": "UNC_M2HBM_PREFCAM_RxC_DEALLOCS.1LM_POSTED", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_PREFCAM_RxC_DEALLOCS.CIS", + "EventCode": "0x62", + "EventName": "UNC_M2HBM_PREFCAM_RxC_DEALLOCS.CIS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_PREFCAM_RxC_DEALLOCS.SQUASHED", + "EventCode": "0x62", + "EventName": "UNC_M2HBM_PREFCAM_RxC_DEALLOCS.SQUASHED", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "UNC_M2HBM_PREFCAM_RxC_OCCUPANCY", + "EventCode": "0x60", + "EventName": "UNC_M2HBM_PREFCAM_RxC_OCCUPANCY", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "Unit": "M2HBM" + }, + { + "BriefDescription": "AD Ingress (from CMS) : AD Ingress (from CMS) Allocations", + "EventCode": "0x02", + "EventName": "UNC_M2HBM_RxC_AD.INSERTS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "AD Ingress (from CMS) : AD Ingress (from CMS) Allocations", + "EventCode": "0x02", + "EventName": "UNC_M2HBM_RxC_AD_INSERTS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "AD Ingress (from CMS) Occupancy", + "EventCode": "0x03", + "EventName": "UNC_M2HBM_RxC_AD_OCCUPANCY", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Ingress (from CMS) : BL Ingress (from CMS) Allocations", + "EventCode": "0x04", + "EventName": "UNC_M2HBM_RxC_BL.INSERTS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts anytime a BL packet is added to Ingress", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Ingress (from CMS) : BL Ingress (from CMS) Allocations", + "EventCode": "0x04", + "EventName": "UNC_M2HBM_RxC_BL_INSERTS", + "PerPkg": "1", + "PublicDescription": "Counts anytime a BL packet is added to Ingress", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Ingress (from CMS) Occupancy", + "EventCode": "0x05", + "EventName": "UNC_M2HBM_RxC_BL_OCCUPANCY", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number AD Ingress Credits", + "EventCode": "0x2e", + "EventName": "UNC_M2HBM_TGR_AD_CREDITS", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Number BL Ingress Credits", + "EventCode": "0x2f", + "EventName": "UNC_M2HBM_TGR_BL_CREDITS", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Tracker Inserts : Channel 0", + "EventCode": "0x32", + "EventName": "UNC_M2HBM_TRACKER_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x104", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Tracker Inserts : Channel 1", + "EventCode": "0x32", + "EventName": "UNC_M2HBM_TRACKER_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x204", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Tracker Occupancy : Channel 0", + "EventCode": "0x33", + "EventName": "UNC_M2HBM_TRACKER_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Tracker Occupancy : Channel 1", + "EventCode": "0x33", + "EventName": "UNC_M2HBM_TRACKER_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "AD Egress (to CMS) : AD Egress (to CMS) Allocations", + "EventCode": "0x06", + "EventName": "UNC_M2HBM_TxC_AD.INSERTS", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts anytime a AD packet is added to Egress", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "AD Egress (to CMS) : AD Egress (to CMS) Allocations", + "EventCode": "0x06", + "EventName": "UNC_M2HBM_TxC_AD_INSERTS", + "PerPkg": "1", + "PublicDescription": "Counts anytime a AD packet is added to Egress", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "AD Egress (to CMS) Occupancy", + "EventCode": "0x07", + "EventName": "UNC_M2HBM_TxC_AD_OCCUPANCY", + "PerPkg": "1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Egress (to CMS) : Inserts - CMS0 - Near Side", + "EventCode": "0x0E", + "EventName": "UNC_M2HBM_TxC_BL.INSERTS_CMS0", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of BL transactions to CMS add port 0", + "UMask": "0x101", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Egress (to CMS) : Inserts - CMS1 - Far Side", + "EventCode": "0x0E", + "EventName": "UNC_M2HBM_TxC_BL.INSERTS_CMS1", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of BL transactions to CMS add port 1", + "UMask": "0x201", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Egress (to CMS) Occupancy : All", + "EventCode": "0x0f", + "EventName": "UNC_M2HBM_TxC_BL_OCCUPANCY.ALL", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Egress (to CMS) Occupancy : Common Mesh Stop - Near Side", + "EventCode": "0x0f", + "EventName": "UNC_M2HBM_TxC_BL_OCCUPANCY.CMS0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "BL Egress (to CMS) Occupancy : Common Mesh Stop - Far Side", + "EventCode": "0x0f", + "EventName": "UNC_M2HBM_TxC_BL_OCCUPANCY.CMS1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "WPQ Flush : Channel 0", + "EventCode": "0x42", + "EventName": "UNC_M2HBM_WPQ_FLUSH.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "WPQ Flush : Channel 1", + "EventCode": "0x42", + "EventName": "UNC_M2HBM_WPQ_FLUSH.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "M2M and iMC WPQ Cycles w/Credits - Regular : Channel 0", + "EventCode": "0x37", + "EventName": "UNC_M2HBM_WPQ_NO_REG_CRD.CHN0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "M2M and iMC WPQ Cycles w/Credits - Regular : Channel 1", + "EventCode": "0x37", + "EventName": "UNC_M2HBM_WPQ_NO_REG_CRD.CHN1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "M2M and iMC WPQ Cycles w/Credits - Special : Channel 0", + "EventCode": "0x38", + "EventName": "UNC_M2HBM_WPQ_NO_SPEC_CRD.CHN0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "M2M and iMC WPQ Cycles w/Credits - Special : Channel 1", + "EventCode": "0x38", + "EventName": "UNC_M2HBM_WPQ_NO_SPEC_CRD.CHN1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Inserts : Channel 0", + "EventCode": "0x40", + "EventName": "UNC_M2HBM_WR_TRACKER_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Inserts : Channel 1", + "EventCode": "0x40", + "EventName": "UNC_M2HBM_WR_TRACKER_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Non-Posted Inserts : Channel 0", + "EventCode": "0x4d", + "EventName": "UNC_M2HBM_WR_TRACKER_NONPOSTED_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Non-Posted Inserts : Channel 1", + "EventCode": "0x4d", + "EventName": "UNC_M2HBM_WR_TRACKER_NONPOSTED_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Non-Posted Occupancy : Channel 0", + "EventCode": "0x4c", + "EventName": "UNC_M2HBM_WR_TRACKER_NONPOSTED_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Non-Posted Occupancy : Channel 1", + "EventCode": "0x4c", + "EventName": "UNC_M2HBM_WR_TRACKER_NONPOSTED_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Posted Inserts : Channel 0", + "EventCode": "0x48", + "EventName": "UNC_M2HBM_WR_TRACKER_POSTED_INSERTS.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Posted Inserts : Channel 1", + "EventCode": "0x48", + "EventName": "UNC_M2HBM_WR_TRACKER_POSTED_INSERTS.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Posted Occupancy : Channel 0", + "EventCode": "0x47", + "EventName": "UNC_M2HBM_WR_TRACKER_POSTED_OCCUPANCY.CH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Write Tracker Posted Occupancy : Channel 1", + "EventCode": "0x47", + "EventName": "UNC_M2HBM_WR_TRACKER_POSTED_OCCUPANCY.CH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "M2HBM" + }, + { + "BriefDescription": "Activate due to read, write, underfill, or bypass", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.ALL", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0xff", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Activate due to read", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x11", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count : Activate due to Read in PCH0", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.RD_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count : Activate due to Read in PCH1", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.RD_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x10", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count : Underfill Read transaction on Page Empty or Page Miss", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.UFILL", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x44", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.UFILL_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x4", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.UFILL_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x40", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Activate due to write", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.WR", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x22", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count : Activate due to Write in PCH0", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.WR_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Activate Count : Activate due to Write in PCH1", + "EventCode": "0x02", + "EventName": "UNC_MCHBM_ACT_COUNT.WR_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Activate commands sent on this channel. Activate commands are issued to open up a page on the HBM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0x20", + "Unit": "MCHBM" + }, + { + "BriefDescription": "All CAS commands issued", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.ALL", + "PerPkg": "1", + "UMask": "0xff", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Pseudo Channel 0", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.PCH0", + "PerPkg": "1", + "PublicDescription": "HBM RD_CAS and WR_CAS Commands", + "UMask": "0x40", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Pseudo Channel 1", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.PCH1", + "PerPkg": "1", + "PublicDescription": "HBM RD_CAS and WR_CAS Commands", + "UMask": "0x80", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read CAS commands issued (regular and underfill)", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.RD", + "PerPkg": "1", + "UMask": "0xcf", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Regular read CAS commands with precharge", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.RD_PRE_REG", + "PerPkg": "1", + "UMask": "0xc2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Underfill read CAS commands with precharge", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.RD_PRE_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc8", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Regular read CAS commands issued (does not include underfills)", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.RD_REG", + "PerPkg": "1", + "UMask": "0xc1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Underfill read CAS commands issued", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.RD_UNDERFILL", + "PerPkg": "1", + "UMask": "0xc4", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write CAS commands issued", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.WR", + "PerPkg": "1", + "UMask": "0xf0", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM RD_CAS and WR_CAS Commands. : HBM WR_CAS commands w/o auto-pre", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.WR_NONPRE", + "PerPkg": "1", + "UMask": "0xd0", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write CAS commands with precharge", + "EventCode": "0x05", + "EventName": "UNC_MCHBM_CAS_COUNT.WR_PRE", + "PerPkg": "1", + "UMask": "0xe0", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Pseudo Channel 0", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.PCH0", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Pseudo Channel 1", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.PCH1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read CAS Command in Interleaved Mode (32B)", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.RD_32B", + "PerPkg": "1", + "UMask": "0xc8", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read CAS Command in Regular Mode (64B) in Pseudochannel 0", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.RD_64B", + "PerPkg": "1", + "UMask": "0xc1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Underfill Read CAS Command in Interleaved Mode (32B)", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.RD_UFILL_32B", + "PerPkg": "1", + "UMask": "0xd0", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Underfill Read CAS Command in Regular Mode (64B) in Pseudochannel 1", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.RD_UFILL_64B", + "PerPkg": "1", + "UMask": "0xc2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write CAS Command in Interleaved Mode (32B)", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.WR_32B", + "PerPkg": "1", + "UMask": "0xe0", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write CAS Command in Regular Mode (64B) in Pseudochannel 0", + "EventCode": "0x06", + "EventName": "UNC_MCHBM_CAS_ISSUED_REQ_LEN.WR_64B", + "PerPkg": "1", + "UMask": "0xc4", + "Unit": "MCHBM" + }, + { + "BriefDescription": "IMC Clockticks at DCLK frequency", + "EventCode": "0x01", + "EventName": "UNC_MCHBM_CLOCKTICKS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge All Commands", + "EventCode": "0x44", + "EventName": "UNC_MCHBM_HBM_PREALL.PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of times that the precharge all command was sent.", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge All Commands", + "EventCode": "0x44", + "EventName": "UNC_MCHBM_HBM_PREALL.PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of times that the precharge all command was sent.", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "All Precharge Commands", + "EventCode": "0x44", + "EventName": "UNC_MCHBM_HBM_PRE_ALL", + "PerPkg": "1", + "PublicDescription": "Precharge All Commands: Counts the number of times that the precharge all command was sent.", + "UMask": "0x3", + "Unit": "MCHBM" + }, + { + "BriefDescription": "IMC Clockticks at HCLK frequency", + "EventCode": "0x01", + "EventName": "UNC_MCHBM_HCLOCKTICKS", + "PerPkg": "1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "All precharge events", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.ALL", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0xff", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Precharge from MC page table", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.PGT", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x88", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands. : Precharges from Page Table", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.PGT_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel. : Equivalent to PAGE_EMPTY", + "UMask": "0x8", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.PGT_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x80", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Precharge due to read on page miss", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.RD", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x11", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands. : Precharge due to read", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.RD_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel. : Precharge from read bank scheduler", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.RD_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x10", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.UFILL", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x44", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.UFILL_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x4", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.UFILL_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x40", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Precharge due to write on page miss", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.WR", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x22", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands. : Precharge due to write", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.WR_PCH0", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel. : Precharge from write bank scheduler", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "HBM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_MCHBM_PRE_COUNT.WR_PCH1", + "PerPkg": "1", + "PublicDescription": "Counts the number of HBM Precharge commands sent on this channel.", + "UMask": "0x20", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Counts the number of cycles where the read buffer has greater than UMASK elements. NOTE: Umask must be set to the maximum number of elements in the queue (24 entries for SPR).", + "EventCode": "0x19", + "EventName": "UNC_MCHBM_RDB_FULL", + "PerPkg": "1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Counts the number of inserts into the read buffer.", + "EventCode": "0x17", + "EventName": "UNC_MCHBM_RDB_INSERTS", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read Data Buffer Inserts", + "EventCode": "0x17", + "EventName": "UNC_MCHBM_RDB_INSERTS.PCH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read Data Buffer Inserts", + "EventCode": "0x17", + "EventName": "UNC_MCHBM_RDB_INSERTS.PCH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Counts the number of elements in the read buffer per cycle.", + "EventCode": "0x1a", + "EventName": "UNC_MCHBM_RDB_OCCUPANCY", + "PerPkg": "1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read Pending Queue Allocations", + "EventCode": "0x10", + "EventName": "UNC_MCHBM_RPQ_INSERTS.PCH0", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Allocations: Counts the number of allocations into the Read Pending Queue. This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory. This includes both ISOCH and non-ISOCH requests.", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read Pending Queue Allocations", + "EventCode": "0x10", + "EventName": "UNC_MCHBM_RPQ_INSERTS.PCH1", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Allocations: Counts the number of allocations into the Read Pending Queue. This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory. This includes both ISOCH and non-ISOCH requests.", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read Pending Queue Occupancy", + "EventCode": "0x80", + "EventName": "UNC_MCHBM_RPQ_OCCUPANCY_PCH0", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Occupancy: Accumulates the occupancies of the Read Pending Queue each cycle. This can then be used to calculate both the average occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The RPQ is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory.", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Read Pending Queue Occupancy", + "EventCode": "0x81", + "EventName": "UNC_MCHBM_RPQ_OCCUPANCY_PCH1", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Occupancy: Accumulates the occupancies of the Read Pending Queue each cycle. This can then be used to calculate both the average occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The RPQ is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory.", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue Allocations", + "EventCode": "0x20", + "EventName": "UNC_MCHBM_WPQ_INSERTS.PCH0", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Allocations: Counts the number of allocations into the Write Pending Queue. This can then be used to calculate the average queuing latency (in conjunction with the WPQ occupancy count). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC. They deallocate after being issued. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC.", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue Allocations", + "EventCode": "0x20", + "EventName": "UNC_MCHBM_WPQ_INSERTS.PCH1", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Allocations: Counts the number of allocations into the Write Pending Queue. This can then be used to calculate the average queuing latency (in conjunction with the WPQ occupancy count). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC. They deallocate after being issued. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC.", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue Occupancy", + "EventCode": "0x82", + "EventName": "UNC_MCHBM_WPQ_OCCUPANCY_PCH0", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Occupancy: Accumulates the occupancies of the Write Pending Queue each cycle. This can then be used to calculate both the average queue occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after being issued to memory. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC. This is not to be confused with actually performing the write. Therefore, the average latency for this queue is actually not useful for deconstruction intermediate write latencies. So, we provide filtering based on if the request has posted or not. By using the not posted filter, we can track how long writes spent in the iMC before completions were sent to the HA. The posted filter, on the other hand, provides information about how much queueing is actually happening in the iMC for writes before they are actually issued to memory. High average occupancies will generally coincide with high write major mode counts.", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue Occupancy", + "EventCode": "0x83", + "EventName": "UNC_MCHBM_WPQ_OCCUPANCY_PCH1", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Occupancy: Accumulates the occupancies of the Write Pending Queue each cycle. This can then be used to calculate both the average queue occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after being issued to memory. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC. This is not to be confused with actually performing the write. Therefore, the average latency for this queue is actually not useful for deconstruction intermediate write latencies. So, we provide filtering based on if the request has posted or not. By using the not posted filter, we can track how long writes spent in the iMC before completions were sent to the HA. The posted filter, on the other hand, provides information about how much queueing is actually happening in the iMC for writes before they are actually issued to memory. High average occupancies will generally coincide with high write major mode counts.", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x23", + "EventName": "UNC_MCHBM_WPQ_READ_HIT", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x23", + "EventName": "UNC_MCHBM_WPQ_READ_HIT.PCH0", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue CAM Match: Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x23", + "EventName": "UNC_MCHBM_WPQ_READ_HIT.PCH1", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue CAM Match: Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x24", + "EventName": "UNC_MCHBM_WPQ_WRITE_HIT", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x24", + "EventName": "UNC_MCHBM_WPQ_WRITE_HIT.PCH0", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue CAM Match: Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "UMask": "0x1", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x24", + "EventName": "UNC_MCHBM_WPQ_WRITE_HIT.PCH1", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue CAM Match: Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "UMask": "0x2", + "Unit": "MCHBM" + }, + { + "BriefDescription": "Activate due to read, write, underfill, or bypass", + "EventCode": "0x02", + "EventName": "UNC_M_ACT_COUNT.ALL", + "PerPkg": "1", + "PublicDescription": "DRAM Activate Count : Counts the number of DRAM Activate commands sent on this channel. Activate commands are issued to open up a page on the DRAM devices so that it can be read or written to with a CAS. One can calculate the number of Page Misses by subtracting the number of Page Miss precharges from the number of Activates.", + "UMask": "0xff", + "Unit": "iMC" + }, + { + "BriefDescription": "All DRAM CAS commands issued", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.ALL", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : All DRAM Read and Write actions : DRAM RD_CAS and WR_CAS Commands : Counts the total number of DRAM CAS commands issued on this channel.", + "UMask": "0xff", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM RD_CAS and WR_CAS Commands. : Pseudo Channel 0", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.PCH0", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : Pseudo Channel 0 : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM RD_CAS and WR_CAS Commands. : Pseudo Channel 1", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.PCH1", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : Pseudo Channel 1 : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0x80", + "Unit": "iMC" + }, + { + "BriefDescription": "All DRAM read CAS commands issued (including underfills)", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.RD", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands : Counts the total number of DRAM Read CAS commands issued on this channel. This includes underfills.", + "UMask": "0xcf", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM RD_CAS and WR_CAS Commands.", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.RD_PRE_REG", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0xc2", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM RD_CAS and WR_CAS Commands.", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.RD_PRE_UNDERFILL", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0xc8", + "Unit": "iMC" + }, + { + "BriefDescription": "All DRAM read CAS commands issued (does not include underfills)", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.RD_REG", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : DRAM RD_CAS commands w/out auto-pre : DRAM RD_CAS and WR_CAS Commands : Counts the total number or DRAM Read CAS commands issued on this channel. This includes both regular RD CAS commands as well as those with implicit Precharge. We do not filter based on major mode, as RD_CAS is not issued during WMM (with the exception of underfills).", + "UMask": "0xc1", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM underfill read CAS commands issued", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.RD_UNDERFILL", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : Underfill Read Issued : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0xc4", + "Unit": "iMC" + }, + { + "BriefDescription": "All DRAM write CAS commands issued", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.WR", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands : Counts the total number of DRAM Write CAS commands issued on this channel.", + "UMask": "0xf0", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM RD_CAS and WR_CAS Commands. : DRAM WR_CAS commands w/o auto-pre", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.WR_NONPRE", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : DRAM WR_CAS commands w/o auto-pre : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0xd0", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM RD_CAS and WR_CAS Commands.", + "EventCode": "0x05", + "EventName": "UNC_M_CAS_COUNT.WR_PRE", + "PerPkg": "1", + "PublicDescription": "DRAM RD_CAS and WR_CAS Commands. : DRAM RD_CAS and WR_CAS Commands", + "UMask": "0xe0", + "Unit": "iMC" + }, + { + "BriefDescription": "Pseudo Channel 0", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.PCH0", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": "Pseudo Channel 1", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.PCH1", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "iMC" + }, + { + "BriefDescription": "Read CAS Command in Interleaved Mode (32B)", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.RD_32B", + "PerPkg": "1", + "UMask": "0xc8", + "Unit": "iMC" + }, + { + "BriefDescription": "Read CAS Command in Regular Mode (64B) in Pseudochannel 0", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.RD_64B", + "PerPkg": "1", + "UMask": "0xc1", + "Unit": "iMC" + }, + { + "BriefDescription": "Underfill Read CAS Command in Interleaved Mode (32B)", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.RD_UFILL_32B", + "PerPkg": "1", + "UMask": "0xd0", + "Unit": "iMC" + }, + { + "BriefDescription": "Underfill Read CAS Command in Regular Mode (64B) in Pseudochannel 1", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.RD_UFILL_64B", + "PerPkg": "1", + "UMask": "0xc2", + "Unit": "iMC" + }, + { + "BriefDescription": "Write CAS Command in Interleaved Mode (32B)", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.WR_32B", + "PerPkg": "1", + "UMask": "0xe0", + "Unit": "iMC" + }, + { + "BriefDescription": "Write CAS Command in Regular Mode (64B) in Pseudochannel 0", + "EventCode": "0x06", + "EventName": "UNC_M_CAS_ISSUED_REQ_LEN.WR_64B", + "PerPkg": "1", + "UMask": "0xc4", + "Unit": "iMC" + }, + { + "BriefDescription": "IMC Clockticks at DCLK frequency", + "EventCode": "0x01", + "EventName": "UNC_M_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of DRAM DCLK clock cycles while the event is enabled", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge All Commands", + "EventCode": "0x44", + "EventName": "UNC_M_DRAM_PRE_ALL", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge All Commands : Counts the number of times that the precharge all command was sent.", + "UMask": "0x3", + "Unit": "iMC" + }, + { + "BriefDescription": "IMC Clockticks at HCLK frequency", + "EventCode": "0x01", + "EventName": "UNC_M_HCLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of DRAM HCLK clock cycles while the event is enabled", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_PCLS.RD", + "EventCode": "0xa0", + "EventName": "UNC_M_PCLS.RD", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_PCLS.TOTAL", + "EventCode": "0xa0", + "EventName": "UNC_M_PCLS.TOTAL", + "PerPkg": "1", + "UMask": "0xf", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_PCLS.WR", + "EventCode": "0xa0", + "EventName": "UNC_M_PCLS.WR", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue inserts", + "EventCode": "0xe3", + "EventName": "UNC_M_PMM_RPQ_INSERTS", + "PerPkg": "1", + "PublicDescription": "Counts number of read requests allocated in the PMM Read Pending Queue.", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue occupancy", + "EventCode": "0xe0", + "EventName": "UNC_M_PMM_RPQ_OCCUPANCY.ALL_SCH0", + "PerPkg": "1", + "PublicDescription": "Accumulates the per cycle occupancy of the PMM Read Pending Queue.", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue occupancy", + "EventCode": "0xe0", + "EventName": "UNC_M_PMM_RPQ_OCCUPANCY.ALL_SCH1", + "PerPkg": "1", + "PublicDescription": "Accumulates the per cycle occupancy of the PMM Read Pending Queue.", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue Occupancy", + "EventCode": "0xE0", + "EventName": "UNC_M_PMM_RPQ_OCCUPANCY.GNT_WAIT_SCH0", + "PerPkg": "1", + "PublicDescription": "PMM Read Pending Queue Occupancy : Accumulates the per cycle occupancy of the PMM Read Pending Queue.", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue Occupancy", + "EventCode": "0xE0", + "EventName": "UNC_M_PMM_RPQ_OCCUPANCY.GNT_WAIT_SCH1", + "PerPkg": "1", + "PublicDescription": "PMM Read Pending Queue Occupancy : Accumulates the per cycle occupancy of the PMM Read Pending Queue.", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue Occupancy", + "EventCode": "0xe0", + "EventName": "UNC_M_PMM_RPQ_OCCUPANCY.NO_GNT_SCH0", + "PerPkg": "1", + "PublicDescription": "Accumulates the per cycle occupancy of the PMM Read Pending Queue.", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Read Pending Queue Occupancy", + "EventCode": "0xe0", + "EventName": "UNC_M_PMM_RPQ_OCCUPANCY.NO_GNT_SCH1", + "PerPkg": "1", + "PublicDescription": "Accumulates the per cycle occupancy of the PMM Read Pending Queue.", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM (for IXP) Write Queue Cycles Not Empty", + "EventCode": "0xe5", + "EventName": "UNC_M_PMM_WPQ_CYCLES_NE", + "PerPkg": "1", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Write Pending Queue inserts", + "EventCode": "0xe7", + "EventName": "UNC_M_PMM_WPQ_INSERTS", + "PerPkg": "1", + "PublicDescription": "Counts number of write requests allocated in the PMM Write Pending Queue.", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Write Pending Queue Occupancy", + "EventCode": "0xe4", + "EventName": "UNC_M_PMM_WPQ_OCCUPANCY.ALL", + "PerPkg": "1", + "PublicDescription": "PMM Write Pending Queue Occupancy : Accumulates the per cycle occupancy of the Write Pending Queue to the PMM DIMM.", + "UMask": "0x3", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Write Pending Queue Occupancy", + "EventCode": "0xE4", + "EventName": "UNC_M_PMM_WPQ_OCCUPANCY.ALL_SCH0", + "PerPkg": "1", + "PublicDescription": "PMM Write Pending Queue Occupancy : Accumulates the per cycle occupancy of the PMM Write Pending Queue.", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM Write Pending Queue Occupancy", + "EventCode": "0xE4", + "EventName": "UNC_M_PMM_WPQ_OCCUPANCY.ALL_SCH1", + "PerPkg": "1", + "PublicDescription": "PMM Write Pending Queue Occupancy : Accumulates the per cycle occupancy of the PMM Write Pending Queue.", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM (for IXP) Write Pending Queue Occupancy", + "EventCode": "0xe4", + "EventName": "UNC_M_PMM_WPQ_OCCUPANCY.CAS", + "PerPkg": "1", + "PublicDescription": "PMM (for IXP) Write Pending Queue Occupancy : Accumulates the per cycle occupancy of the Write Pending Queue to the IXP DIMM.", + "UMask": "0xc", + "Unit": "iMC" + }, + { + "BriefDescription": "PMM (for IXP) Write Pending Queue Occupancy", + "EventCode": "0xe4", + "EventName": "UNC_M_PMM_WPQ_OCCUPANCY.PWR", + "PerPkg": "1", + "PublicDescription": "PMM (for IXP) Write Pending Queue Occupancy : Accumulates the per cycle occupancy of the Write Pending Queue to the IXP DIMM.", + "UMask": "0x30", + "Unit": "iMC" + }, + { + "BriefDescription": "Channel PPD Cycles", + "EventCode": "0x85", + "EventName": "UNC_M_POWER_CHANNEL_PPD", + "PerPkg": "1", + "PublicDescription": "Channel PPD Cycles : Number of cycles when all the ranks in the channel are in PPD mode. If IBT=off is enabled, then this can be used to count those cycles. If it is not enabled, then this can count the number of cycles when that could have been taken advantage of.", + "Unit": "iMC" + }, + { + "BriefDescription": "CKE_ON_CYCLES by Rank : DIMM ID", + "EventCode": "0x47", + "EventName": "UNC_M_POWER_CKE_CYCLES.LOW_0", + "PerPkg": "1", + "PublicDescription": "CKE_ON_CYCLES by Rank : DIMM ID : Number of cycles spent in CKE ON mode. The filter allows you to select a rank to monitor. If multiple ranks are in CKE ON mode at one time, the counter will ONLY increment by one rather than doing accumulation. Multiple counters will need to be used to track multiple ranks simultaneously. There is no distinction between the different CKE modes (APD, PPDS, PPDF). This can be determined based on the system programming. These events should commonly be used with Invert to get the number of cycles in power saving mode. Edge Detect is also useful here. Make sure that you do NOT use Invert with Edge Detect (this just confuses the system and is not necessary).", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "CKE_ON_CYCLES by Rank : DIMM ID", + "EventCode": "0x47", + "EventName": "UNC_M_POWER_CKE_CYCLES.LOW_1", + "PerPkg": "1", + "PublicDescription": "CKE_ON_CYCLES by Rank : DIMM ID : Number of cycles spent in CKE ON mode. The filter allows you to select a rank to monitor. If multiple ranks are in CKE ON mode at one time, the counter will ONLY increment by one rather than doing accumulation. Multiple counters will need to be used to track multiple ranks simultaneously. There is no distinction between the different CKE modes (APD, PPDS, PPDF). This can be determined based on the system programming. These events should commonly be used with Invert to get the number of cycles in power saving mode. Edge Detect is also useful here. Make sure that you do NOT use Invert with Edge Detect (this just confuses the system and is not necessary).", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "CKE_ON_CYCLES by Rank : DIMM ID", + "EventCode": "0x47", + "EventName": "UNC_M_POWER_CKE_CYCLES.LOW_2", + "PerPkg": "1", + "PublicDescription": "CKE_ON_CYCLES by Rank : DIMM ID : Number of cycles spent in CKE ON mode. The filter allows you to select a rank to monitor. If multiple ranks are in CKE ON mode at one time, the counter will ONLY increment by one rather than doing accumulation. Multiple counters will need to be used to track multiple ranks simultaneously. There is no distinction between the different CKE modes (APD, PPDS, PPDF). This can be determined based on the system programming. These events should commonly be used with Invert to get the number of cycles in power saving mode. Edge Detect is also useful here. Make sure that you do NOT use Invert with Edge Detect (this just confuses the system and is not necessary).", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "CKE_ON_CYCLES by Rank : DIMM ID", + "EventCode": "0x47", + "EventName": "UNC_M_POWER_CKE_CYCLES.LOW_3", + "PerPkg": "1", + "PublicDescription": "CKE_ON_CYCLES by Rank : DIMM ID : Number of cycles spent in CKE ON mode. The filter allows you to select a rank to monitor. If multiple ranks are in CKE ON mode at one time, the counter will ONLY increment by one rather than doing accumulation. Multiple counters will need to be used to track multiple ranks simultaneously. There is no distinction between the different CKE modes (APD, PPDS, PPDF). This can be determined based on the system programming. These events should commonly be used with Invert to get the number of cycles in power saving mode. Edge Detect is also useful here. Make sure that you do NOT use Invert with Edge Detect (this just confuses the system and is not necessary).", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "Throttle Cycles for Rank 0", + "EventCode": "0x86", + "EventName": "UNC_M_POWER_CRIT_THROTTLE_CYCLES.SLOT0", + "PerPkg": "1", + "PublicDescription": "Throttle Cycles for Rank 0 : Counts the number of cycles while the iMC is being throttled by either thermal constraints or by the PCU throttling. It is not possible to distinguish between the two. This can be filtered by rank. If multiple ranks are selected and are being throttled at the same time, the counter will only increment by 1. : Thermal throttling is performed per DIMM. We support 3 DIMMs per channel. This ID allows us to filter by ID.", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Throttle Cycles for Rank 0", + "EventCode": "0x86", + "EventName": "UNC_M_POWER_CRIT_THROTTLE_CYCLES.SLOT1", + "PerPkg": "1", + "PublicDescription": "Throttle Cycles for Rank 0 : Counts the number of cycles while the iMC is being throttled by either thermal constraints or by the PCU throttling. It is not possible to distinguish between the two. This can be filtered by rank. If multiple ranks are selected and are being throttled at the same time, the counter will only increment by 1.", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Clock-Enabled Self-Refresh", + "EventCode": "0x43", + "EventName": "UNC_M_POWER_SELF_REFRESH", + "PerPkg": "1", + "PublicDescription": "Clock-Enabled Self-Refresh : Counts the number of cycles when the iMC is in self-refresh and the iMC still has a clock. This happens in some package C-states. For example, the PCU may ask the iMC to enter self-refresh even though some of the cores are still processing. One use of this is for Monroe technology. Self-refresh is required during package C3 and C6, but there is no clock in the iMC at this time, so it is not possible to count these cases.", + "Unit": "iMC" + }, + { + "BriefDescription": "Precharge due to read, write, underfill, or PGT.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.ALL", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0xff", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.PGT", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x88", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Precharges from Page Table", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.PGT_PCH0", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Precharges from Page Table : Counts the number of DRAM Precharge commands sent on this channel. : Equivalent to PAGE_EMPTY", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.PGT_PCH1", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x80", + "Unit": "iMC" + }, + { + "BriefDescription": "Precharge due to read on page miss", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.RD", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x11", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Precharge due to read", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.RD_PCH0", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Precharge due to read : Counts the number of DRAM Precharge commands sent on this channel. : Precharge from read bank scheduler", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.RD_PCH1", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.UFILL", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x44", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.UFILL_PCH0", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.UFILL_PCH1", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": "Precharge due to write on page miss", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.WR", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x22", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands. : Precharge due to write", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.WR_PCH0", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Precharge due to write : Counts the number of DRAM Precharge commands sent on this channel. : Precharge from write bank scheduler", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "DRAM Precharge commands.", + "EventCode": "0x03", + "EventName": "UNC_M_PRE_COUNT.WR_PCH1", + "PerPkg": "1", + "PublicDescription": "DRAM Precharge commands. : Counts the number of DRAM Precharge commands sent on this channel.", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "Counts the number of cycles where the read buffer has greater than UMASK elements. This includes reads to both DDR and PMEM. NOTE: Umask must be set to the maximum number of elements in the queue (24 entries for SPR).", + "EventCode": "0x19", + "EventName": "UNC_M_RDB_FULL", + "PerPkg": "1", + "Unit": "iMC" + }, + { + "BriefDescription": "Counts the number of inserts into the read buffer destined for DDR. Does not count reads destined for PMEM.", + "EventCode": "0x17", + "EventName": "UNC_M_RDB_INSERTS", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Data Buffer Inserts", + "EventCode": "0x17", + "EventName": "UNC_M_RDB_INSERTS.PCH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Data Buffer Inserts", + "EventCode": "0x17", + "EventName": "UNC_M_RDB_INSERTS.PCH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Counts the number of cycles where there's at least one element in the read buffer. This includes reads to both DDR and PMEM.", + "EventCode": "0x18", + "EventName": "UNC_M_RDB_NE", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Data Buffer Not Empty", + "EventCode": "0x18", + "EventName": "UNC_M_RDB_NE.PCH0", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Data Buffer Not Empty", + "EventCode": "0x18", + "EventName": "UNC_M_RDB_NE.PCH1", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Counts the number of cycles where there's at least one element in the read buffer. This includes reads to both DDR and PMEM.", + "EventCode": "0x18", + "EventName": "UNC_M_RDB_NOT_EMPTY", + "PerPkg": "1", + "UMask": "0x3", + "Unit": "iMC" + }, + { + "BriefDescription": "Counts the number of elements in the read buffer, including reads to both DDR and PMEM.", + "EventCode": "0x1a", + "EventName": "UNC_M_RDB_OCCUPANCY", + "PerPkg": "1", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Pending Queue Allocations", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.PCH0", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Allocations : Counts the number of allocations into the Read Pending Queue. This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory. This includes both ISOCH and non-ISOCH requests.", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Pending Queue Allocations", + "EventCode": "0x10", + "EventName": "UNC_M_RPQ_INSERTS.PCH1", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Allocations : Counts the number of allocations into the Read Pending Queue. This queue is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory. This includes both ISOCH and non-ISOCH requests.", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Pending Queue Occupancy", + "EventCode": "0x80", + "EventName": "UNC_M_RPQ_OCCUPANCY_PCH0", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Occupancy : Accumulates the occupancies of the Read Pending Queue each cycle. This can then be used to calculate both the average occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The RPQ is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory.", + "Unit": "iMC" + }, + { + "BriefDescription": "Read Pending Queue Occupancy", + "EventCode": "0x81", + "EventName": "UNC_M_RPQ_OCCUPANCY_PCH1", + "PerPkg": "1", + "PublicDescription": "Read Pending Queue Occupancy : Accumulates the occupancies of the Read Pending Queue each cycle. This can then be used to calculate both the average occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The RPQ is used to schedule reads out to the memory controller and to track the requests. Requests allocate into the RPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after the CAS command has been issued to memory.", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard accepts", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.ACCEPTS", + "PerPkg": "1", + "UMask": "0x5", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : Write Accepts", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.FM_RD_CMPS", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : Write Rejects", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.FM_WR_CMPS", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : FM read completions", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.NM_RD_CMPS", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : FM write completions", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.NM_WR_CMPS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : Read Accepts", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.RD_ACCEPTS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : Read Rejects", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.RD_REJECTS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard rejects", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.REJECTS", + "PerPkg": "1", + "UMask": "0xa", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : NM read completions", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.WR_ACCEPTS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Accesses : NM write completions", + "EventCode": "0xd2", + "EventName": "UNC_M_SB_ACCESSES.WR_REJECTS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": ": Alloc", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.ALLOC", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": ": Dealloc", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.DEALLOC", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Write Starved", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.FM_RD_STARVED", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Write Starved", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.FM_TGR_WR_STARVED", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Read Starved", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.FM_WR_STARVED", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": ": Valid", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.NM_RD_STARVED", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read Starved", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.NM_WR_STARVED", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": ": Reject", + "EventCode": "0xd9", + "EventName": "UNC_M_SB_CANARY.VLD", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Cycles Full", + "EventCode": "0xd1", + "EventName": "UNC_M_SB_CYCLES_FULL", + "PerPkg": "1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Cycles Not-Empty", + "EventCode": "0xd0", + "EventName": "UNC_M_SB_CYCLES_NE", + "PerPkg": "1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Inserts : Block region reads", + "EventCode": "0xd6", + "EventName": "UNC_M_SB_INSERTS.BLOCK_RDS", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Inserts : Block region writes", + "EventCode": "0xd6", + "EventName": "UNC_M_SB_INSERTS.BLOCK_WRS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Inserts : Persistent Mem reads", + "EventCode": "0xd6", + "EventName": "UNC_M_SB_INSERTS.PMM_RDS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Inserts : Persistent Mem writes", + "EventCode": "0xd6", + "EventName": "UNC_M_SB_INSERTS.PMM_WRS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Inserts : Reads", + "EventCode": "0xd6", + "EventName": "UNC_M_SB_INSERTS.RDS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Inserts : Writes", + "EventCode": "0xd6", + "EventName": "UNC_M_SB_INSERTS.WRS", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Occupancy : Block region reads", + "EventCode": "0xd5", + "EventName": "UNC_M_SB_OCCUPANCY.BLOCK_RDS", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Occupancy : Block region writes", + "EventCode": "0xd5", + "EventName": "UNC_M_SB_OCCUPANCY.BLOCK_WRS", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Occupancy : Persistent Mem reads", + "EventCode": "0xd5", + "EventName": "UNC_M_SB_OCCUPANCY.PMM_RDS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Occupancy : Persistent Mem writes", + "EventCode": "0xd5", + "EventName": "UNC_M_SB_OCCUPANCY.PMM_WRS", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Occupancy : Reads", + "EventCode": "0xd5", + "EventName": "UNC_M_SB_OCCUPANCY.RDS", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Prefetch Inserts : All", + "EventCode": "0xda", + "EventName": "UNC_M_SB_PREF_INSERTS.ALL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Prefetch Inserts : DDR4", + "EventCode": "0xda", + "EventName": "UNC_M_SB_PREF_INSERTS.DDR", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Prefetch Inserts : PMM", + "EventCode": "0xda", + "EventName": "UNC_M_SB_PREF_INSERTS.PMM", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Prefetch Occupancy : All", + "EventCode": "0xdb", + "EventName": "UNC_M_SB_PREF_OCCUPANCY.ALL", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Prefetch Occupancy : DDR4", + "EventCode": "0xdb", + "EventName": "UNC_M_SB_PREF_OCCUPANCY.DDR", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Scoreboard Prefetch Occupancy : Persistent Mem", + "EventCode": "0xDB", + "EventName": "UNC_M_SB_PREF_OCCUPANCY.PMM", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "Number of Scoreboard Requests Rejected", + "EventCode": "0xd4", + "EventName": "UNC_M_SB_REJECT.CANARY", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "Number of Scoreboard Requests Rejected", + "EventCode": "0xd4", + "EventName": "UNC_M_SB_REJECT.DDR_EARLY_CMP", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "Number of Scoreboard Requests Rejected : FM requests rejected due to full address conflict", + "EventCode": "0xd4", + "EventName": "UNC_M_SB_REJECT.FM_ADDR_CNFLT", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Number of Scoreboard Requests Rejected : NM requests rejected due to set conflict", + "EventCode": "0xd4", + "EventName": "UNC_M_SB_REJECT.NM_SET_CNFLT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Number of Scoreboard Requests Rejected : Patrol requests rejected due to set conflict", + "EventCode": "0xd4", + "EventName": "UNC_M_SB_REJECT.PATROL_SET_CNFLT", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Read - Set", + "EventCode": "0xd7", + "EventName": "UNC_M_SB_STRV_ALLOC.FM_RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read - Clear", + "EventCode": "0xd7", + "EventName": "UNC_M_SB_STRV_ALLOC.FM_TGR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Write - Set", + "EventCode": "0xd7", + "EventName": "UNC_M_SB_STRV_ALLOC.FM_WR", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read - Set", + "EventCode": "0xd7", + "EventName": "UNC_M_SB_STRV_ALLOC.NM_RD", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Write - Set", + "EventCode": "0xd7", + "EventName": "UNC_M_SB_STRV_ALLOC.NM_WR", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Read - Set", + "EventCode": "0xde", + "EventName": "UNC_M_SB_STRV_DEALLOC.FM_RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read - Clear", + "EventCode": "0xde", + "EventName": "UNC_M_SB_STRV_DEALLOC.FM_TGR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Write - Set", + "EventCode": "0xde", + "EventName": "UNC_M_SB_STRV_DEALLOC.FM_WR", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read - Set", + "EventCode": "0xde", + "EventName": "UNC_M_SB_STRV_DEALLOC.NM_RD", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Write - Set", + "EventCode": "0xde", + "EventName": "UNC_M_SB_STRV_DEALLOC.NM_WR", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Read", + "EventCode": "0xd8", + "EventName": "UNC_M_SB_STRV_OCC.FM_RD", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read - Clear", + "EventCode": "0xd8", + "EventName": "UNC_M_SB_STRV_OCC.FM_TGR", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": ": Far Mem Write", + "EventCode": "0xd8", + "EventName": "UNC_M_SB_STRV_OCC.FM_WR", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Read", + "EventCode": "0xd8", + "EventName": "UNC_M_SB_STRV_OCC.NM_RD", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": ": Near Mem Write", + "EventCode": "0xd8", + "EventName": "UNC_M_SB_STRV_OCC.NM_WR", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.DDR4_CMP", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.DDR4_CMP", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.NEW", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.NEW", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.OCC", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.OCC", + "PerPkg": "1", + "UMask": "0x80", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.PMM0_CMP", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.PMM0_CMP", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.PMM1_CMP", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.PMM1_CMP", + "PerPkg": "1", + "UMask": "0x20", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.PMM2_CMP", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.PMM2_CMP", + "PerPkg": "1", + "UMask": "0x40", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.RD_HIT", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.RD_HIT", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "UNC_M_SB_TAGGED.RD_MISS", + "EventCode": "0xdd", + "EventName": "UNC_M_SB_TAGGED.RD_MISS", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "2LM Tag check hit in near memory cache (DDR4)", + "EventCode": "0xd3", + "EventName": "UNC_M_TAGCHK.HIT", + "PerPkg": "1", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "2LM Tag check miss, no data at this line", + "EventCode": "0xd3", + "EventName": "UNC_M_TAGCHK.MISS_CLEAN", + "PerPkg": "1", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "2LM Tag check miss, existing data may be evicted to PMM", + "EventCode": "0xd3", + "EventName": "UNC_M_TAGCHK.MISS_DIRTY", + "PerPkg": "1", + "UMask": "0x4", + "Unit": "iMC" + }, + { + "BriefDescription": "2LM Tag check hit due to memory read", + "EventCode": "0xd3", + "EventName": "UNC_M_TAGCHK.NM_RD_HIT", + "PerPkg": "1", + "UMask": "0x8", + "Unit": "iMC" + }, + { + "BriefDescription": "2LM Tag check hit due to memory write", + "EventCode": "0xd3", + "EventName": "UNC_M_TAGCHK.NM_WR_HIT", + "PerPkg": "1", + "UMask": "0x10", + "Unit": "iMC" + }, + { + "BriefDescription": "Write Pending Queue Allocations", + "EventCode": "0x20", + "EventName": "UNC_M_WPQ_INSERTS.PCH0", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Allocations : Counts the number of allocations into the Write Pending Queue. This can then be used to calculate the average queuing latency (in conjunction with the WPQ occupancy count). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC. They deallocate after being issued to DRAM. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC.", + "UMask": "0x1", + "Unit": "iMC" + }, + { + "BriefDescription": "Write Pending Queue Allocations", + "EventCode": "0x20", + "EventName": "UNC_M_WPQ_INSERTS.PCH1", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Allocations : Counts the number of allocations into the Write Pending Queue. This can then be used to calculate the average queuing latency (in conjunction with the WPQ occupancy count). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the CHA to the iMC. They deallocate after being issued to DRAM. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC.", + "UMask": "0x2", + "Unit": "iMC" + }, + { + "BriefDescription": "Write Pending Queue Occupancy", + "EventCode": "0x82", + "EventName": "UNC_M_WPQ_OCCUPANCY_PCH0", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Occupancy : Accumulates the occupancies of the Write Pending Queue each cycle. This can then be used to calculate both the average queue occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after being issued to DRAM. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC. This is not to be confused with actually performing the write to DRAM. Therefore, the average latency for this queue is actually not useful for deconstruction intermediate write latencies. So, we provide filtering based on if the request has posted or not. By using the not posted filter, we can track how long writes spent in the iMC before completions were sent to the HA. The posted filter, on the other hand, provides information about how much queueing is actually happening in the iMC for writes before they are actually issued to memory. High average occupancies will generally coincide with high write major mode counts.", + "Unit": "iMC" + }, + { + "BriefDescription": "Write Pending Queue Occupancy", + "EventCode": "0x83", + "EventName": "UNC_M_WPQ_OCCUPANCY_PCH1", + "PerPkg": "1", + "PublicDescription": "Write Pending Queue Occupancy : Accumulates the occupancies of the Write Pending Queue each cycle. This can then be used to calculate both the average queue occupancy (in conjunction with the number of cycles not empty) and the average latency (in conjunction with the number of allocations). The WPQ is used to schedule write out to the memory controller and to track the writes. Requests allocate into the WPQ soon after they enter the memory controller, and need credits for an entry in this buffer before being sent from the HA to the iMC. They deallocate after being issued to DRAM. Write requests themselves are able to complete (from the perspective of the rest of the system) as soon they have posted to the iMC. This is not to be confused with actually performing the write to DRAM. Therefore, the average latency for this queue is actually not useful for deconstruction intermediate write latencies. So, we provide filtering based on if the request has posted or not. By using the not posted filter, we can track how long writes spent in the iMC before completions were sent to the HA. The posted filter, on the other hand, provides information about how much queueing is actually happening in the iMC for writes before they are actually issued to memory. High average occupancies will generally coincide with high write major mode counts.", + "Unit": "iMC" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x23", + "EventName": "UNC_M_WPQ_READ_HIT", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "Unit": "iMC" + }, + { + "BriefDescription": "Write Pending Queue CAM Match", + "EventCode": "0x24", + "EventName": "UNC_M_WPQ_WRITE_HIT", + "FCMask": "0x00000000", + "PerPkg": "1", + "PortMask": "0x00000000", + "PublicDescription": "Counts the number of times a request hits in the WPQ (write-pending queue). The iMC allows writes and reads to pass up other writes to different addresses. Before a read or a write is issued, it will first CAM the WPQ to see if there is a write pending to that address. When reads hit, they are able to directly pull their data from the WPQ instead of going to memory. Writes that hit will overwrite the existing data. Partial writes that hit will not need to do underfill reads and will simply update their relevant sections.", + "Unit": "iMC" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-power.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-power.json new file mode 100644 index 000000000000..8948e85074f0 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/uncore-power.json @@ -0,0 +1,197 @@ +[ + { + "BriefDescription": "PCU PCLK Clockticks", + "EventCode": "0x01", + "EventName": "UNC_P_CLOCKTICKS", + "PerPkg": "1", + "PublicDescription": "Number of PCU PCLK Clock cycles while the event is enabled", + "Unit": "PCU" + }, + { + "BriefDescription": "UNC_P_CORE_TRANSITION_CYCLES", + "EventCode": "0x60", + "EventName": "UNC_P_CORE_TRANSITION_CYCLES", + "PerPkg": "1", + "Unit": "PCU" + }, + { + "BriefDescription": "UNC_P_DEMOTIONS", + "EventCode": "0x30", + "EventName": "UNC_P_DEMOTIONS", + "PerPkg": "1", + "Unit": "PCU" + }, + { + "BriefDescription": "Phase Shed 0 Cycles", + "EventCode": "0x75", + "EventName": "UNC_P_FIVR_PS_PS0_CYCLES", + "PerPkg": "1", + "PublicDescription": "Phase Shed 0 Cycles : Cycles spent in phase-shedding power state 0", + "Unit": "PCU" + }, + { + "BriefDescription": "Phase Shed 1 Cycles", + "EventCode": "0x76", + "EventName": "UNC_P_FIVR_PS_PS1_CYCLES", + "PerPkg": "1", + "PublicDescription": "Phase Shed 1 Cycles : Cycles spent in phase-shedding power state 1", + "Unit": "PCU" + }, + { + "BriefDescription": "Phase Shed 2 Cycles", + "EventCode": "0x77", + "EventName": "UNC_P_FIVR_PS_PS2_CYCLES", + "PerPkg": "1", + "PublicDescription": "Phase Shed 2 Cycles : Cycles spent in phase-shedding power state 2", + "Unit": "PCU" + }, + { + "BriefDescription": "Phase Shed 3 Cycles", + "EventCode": "0x78", + "EventName": "UNC_P_FIVR_PS_PS3_CYCLES", + "PerPkg": "1", + "PublicDescription": "Phase Shed 3 Cycles : Cycles spent in phase-shedding power state 3", + "Unit": "PCU" + }, + { + "BriefDescription": "AVX256 Frequency Clipping", + "EventCode": "0x49", + "EventName": "UNC_P_FREQ_CLIP_AVX256", + "PerPkg": "1", + "Unit": "PCU" + }, + { + "BriefDescription": "AVX512 Frequency Clipping", + "EventCode": "0x4a", + "EventName": "UNC_P_FREQ_CLIP_AVX512", + "PerPkg": "1", + "Unit": "PCU" + }, + { + "BriefDescription": "Thermal Strongest Upper Limit Cycles", + "EventCode": "0x04", + "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES", + "PerPkg": "1", + "PublicDescription": "Thermal Strongest Upper Limit Cycles : Number of cycles any frequency is reduced due to a thermal limit. Count only if throttling is occurring.", + "Unit": "PCU" + }, + { + "BriefDescription": "Power Strongest Upper Limit Cycles", + "EventCode": "0x05", + "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES", + "PerPkg": "1", + "PublicDescription": "Power Strongest Upper Limit Cycles : Counts the number of cycles when power is the upper limit on frequency.", + "Unit": "PCU" + }, + { + "BriefDescription": "IO P Limit Strongest Lower Limit Cycles", + "EventCode": "0x73", + "EventName": "UNC_P_FREQ_MIN_IO_P_CYCLES", + "PerPkg": "1", + "PublicDescription": "IO P Limit Strongest Lower Limit Cycles : Counts the number of cycles when IO P Limit is preventing us from dropping the frequency lower. This algorithm monitors the needs to the IO subsystem on both local and remote sockets and will maintain a frequency high enough to maintain good IO BW. This is necessary for when all the IA cores on a socket are idle but a user still would like to maintain high IO Bandwidth.", + "Unit": "PCU" + }, + { + "BriefDescription": "Cycles spent changing Frequency", + "EventCode": "0x74", + "EventName": "UNC_P_FREQ_TRANS_CYCLES", + "PerPkg": "1", + "PublicDescription": "Cycles spent changing Frequency : Counts the number of cycles when the system is changing frequency. This can not be filtered by thread ID. One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system.", + "Unit": "PCU" + }, + { + "BriefDescription": "Memory Phase Shedding Cycles", + "EventCode": "0x2f", + "EventName": "UNC_P_MEMORY_PHASE_SHEDDING_CYCLES", + "PerPkg": "1", + "PublicDescription": "Memory Phase Shedding Cycles : Counts the number of cycles that the PCU has triggered memory phase shedding. This is a mode that can be run in the iMC physicals that saves power at the expense of additional latency.", + "Unit": "PCU" + }, + { + "BriefDescription": "Package C State Residency - C0", + "EventCode": "0x2a", + "EventName": "UNC_P_PKG_RESIDENCY_C0_CYCLES", + "PerPkg": "1", + "PublicDescription": "Package C State Residency - C0 : Counts the number of cycles when the package was in C0. This event can be used in conjunction with edge detect to count C0 entrances (or exits using invert). Residency events do not include transition times.", + "Unit": "PCU" + }, + { + "BriefDescription": "Package C State Residency - C2E", + "EventCode": "0x2b", + "EventName": "UNC_P_PKG_RESIDENCY_C2E_CYCLES", + "PerPkg": "1", + "PublicDescription": "Package C State Residency - C2E : Counts the number of cycles when the package was in C2E. This event can be used in conjunction with edge detect to count C2E entrances (or exits using invert). Residency events do not include transition times.", + "Unit": "PCU" + }, + { + "BriefDescription": "Package C State Residency - C6", + "EventCode": "0x2d", + "EventName": "UNC_P_PKG_RESIDENCY_C6_CYCLES", + "PerPkg": "1", + "PublicDescription": "Package C State Residency - C6 : Counts the number of cycles when the package was in C6. This event can be used in conjunction with edge detect to count C6 entrances (or exits using invert). Residency events do not include transition times.", + "Unit": "PCU" + }, + { + "BriefDescription": "UNC_P_PMAX_THROTTLED_CYCLES", + "EventCode": "0x06", + "EventName": "UNC_P_PMAX_THROTTLED_CYCLES", + "PerPkg": "1", + "Unit": "PCU" + }, + { + "BriefDescription": "Number of cores in C0", + "EventCode": "0x35", + "EventName": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C0", + "PerPkg": "1", + "PublicDescription": "Number of cores in C0 : This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with thresholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.", + "Unit": "PCU" + }, + { + "BriefDescription": "Number of cores in C3", + "EventCode": "0x36", + "EventName": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C3", + "PerPkg": "1", + "PublicDescription": "Number of cores in C3 : This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with thresholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.", + "Unit": "PCU" + }, + { + "BriefDescription": "Number of cores in C6", + "EventCode": "0x37", + "EventName": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C6", + "PerPkg": "1", + "PublicDescription": "Number of cores in C6 : This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with thresholding to generate histograms, or with other PCU events and occupancy triggering to capture other details.", + "Unit": "PCU" + }, + { + "BriefDescription": "External Prochot", + "EventCode": "0x0a", + "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES", + "PerPkg": "1", + "PublicDescription": "External Prochot : Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip.", + "Unit": "PCU" + }, + { + "BriefDescription": "Internal Prochot", + "EventCode": "0x09", + "EventName": "UNC_P_PROCHOT_INTERNAL_CYCLES", + "PerPkg": "1", + "PublicDescription": "Internal Prochot : Counts the number of cycles that we are in Internal PROCHOT mode. This mode is triggered when a sensor on the die determines that we are too hot and must throttle to avoid damaging the chip.", + "Unit": "PCU" + }, + { + "BriefDescription": "Total Core C State Transition Cycles", + "EventCode": "0x72", + "EventName": "UNC_P_TOTAL_TRANSITION_CYCLES", + "PerPkg": "1", + "PublicDescription": "Total Core C State Transition Cycles : Number of cycles spent performing core C state transitions across all cores.", + "Unit": "PCU" + }, + { + "BriefDescription": "VR Hot", + "EventCode": "0x42", + "EventName": "UNC_P_VR_HOT_CYCLES", + "PerPkg": "1", + "PublicDescription": "VR Hot : Number of cycles that a CPU SVID VR is hot. Does not cover DRAM VRs", + "Unit": "PCU" + } +] diff --git a/tools/perf/pmu-events/arch/x86/emeraldrapids/virtual-memory.json b/tools/perf/pmu-events/arch/x86/emeraldrapids/virtual-memory.json new file mode 100644 index 000000000000..a1e3b8d2ebe7 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/emeraldrapids/virtual-memory.json @@ -0,0 +1,165 @@ +[ + { + "BriefDescription": "Loads that miss the DTLB and hit the STLB.", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.STLB_HIT", + "PublicDescription": "Counts loads that miss the DTLB (Data TLB) and hit the STLB (Second level TLB).", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a demand load.", + "CounterMask": "1", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_ACTIVE", + "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a demand load.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data loads. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0xe" + }, + { + "BriefDescription": "Page walks completed due to a demand data load to a 1G page.", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_1G", + "PublicDescription": "Counts completed page walks (1G sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Page walks completed due to a demand data load to a 2M/4M page.", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_2M_4M", + "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "Page walks completed due to a demand data load to a 4K page.", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED_4K", + "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data loads. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of page walks outstanding for a demand load in the PMH each cycle.", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_PENDING", + "PublicDescription": "Counts the number of page walks outstanding for a demand load in the PMH (Page Miss Handler) each cycle.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Stores that miss the DTLB and hit the STLB.", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.STLB_HIT", + "PublicDescription": "Counts stores that miss the DTLB (Data TLB) and hit the STLB (2nd Level TLB).", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Cycles when at least one PMH is busy with a page walk for a store.", + "CounterMask": "1", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_ACTIVE", + "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a store.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data stores. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0xe" + }, + { + "BriefDescription": "Page walks completed due to a demand data store to a 1G page.", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_1G", + "PublicDescription": "Counts completed page walks (1G sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x8" + }, + { + "BriefDescription": "Page walks completed due to a demand data store to a 2M/4M page.", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_2M_4M", + "PublicDescription": "Counts completed page walks (2M/4M sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "Page walks completed due to a demand data store to a 4K page.", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED_4K", + "PublicDescription": "Counts completed page walks (4K sizes) caused by demand data stores. This implies address translations missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of page walks outstanding for a store in the PMH each cycle.", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_PENDING", + "PublicDescription": "Counts the number of page walks outstanding for a store in the PMH (Page Miss Handler) each cycle.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Instruction fetch requests that miss the ITLB and hit the STLB.", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.STLB_HIT", + "PublicDescription": "Counts instruction fetch requests that miss the ITLB (Instruction TLB) and hit the STLB (Second-level TLB).", + "SampleAfterValue": "100003", + "UMask": "0x20" + }, + { + "BriefDescription": "Cycles when at least one PMH is busy with a page walk for code (instruction fetch) request.", + "CounterMask": "1", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.WALK_ACTIVE", + "PublicDescription": "Counts cycles when at least one PMH (Page Miss Handler) is busy with a page walk for a code (instruction fetch) request.", + "SampleAfterValue": "100003", + "UMask": "0x10" + }, + { + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts completed page walks (all page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0xe" + }, + { + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (2M/4M)", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.WALK_COMPLETED_2M_4M", + "PublicDescription": "Counts completed page walks (2M/4M page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x4" + }, + { + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (4K)", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.WALK_COMPLETED_4K", + "PublicDescription": "Counts completed page walks (4K page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0x2" + }, + { + "BriefDescription": "Number of page walks outstanding for an outstanding code request in the PMH each cycle.", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.WALK_PENDING", + "PublicDescription": "Counts the number of page walks outstanding for an outstanding code (instruction fetch) request in the PMH (Page Miss Handler) each cycle.", + "SampleAfterValue": "100003", + "UMask": "0x10" + } +] diff --git a/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json index 954e8198c7a5..bef1f5ef6f31 100644 --- a/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json @@ -271,7 +271,7 @@ "EventCode": "0x4", "EventName": "UNC_I_RxR_BL_DRS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -279,7 +279,7 @@ "EventCode": "0x1", "EventName": "UNC_I_RxR_BL_DRS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -287,7 +287,7 @@ "EventCode": "0x7", "EventName": "UNC_I_RxR_BL_DRS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -295,7 +295,7 @@ "EventCode": "0x5", "EventName": "UNC_I_RxR_BL_NCB_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -303,7 +303,7 @@ "EventCode": "0x2", "EventName": "UNC_I_RxR_BL_NCB_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -311,7 +311,7 @@ "EventCode": "0x8", "EventName": "UNC_I_RxR_BL_NCB_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -319,7 +319,7 @@ "EventCode": "0x6", "EventName": "UNC_I_RxR_BL_NCS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -327,7 +327,7 @@ "EventCode": "0x3", "EventName": "UNC_I_RxR_BL_NCS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -335,7 +335,7 @@ "EventCode": "0x9", "EventName": "UNC_I_RxR_BL_NCS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { diff --git a/tools/perf/pmu-events/arch/x86/icelake/icl-metrics.json b/tools/perf/pmu-events/arch/x86/icelake/icl-metrics.json index a6eed0d9a26d..b43a6c6d8b7f 100644 --- a/tools/perf/pmu-events/arch/x86/icelake/icl-metrics.json +++ b/tools/perf/pmu-events/arch/x86/icelake/icl-metrics.json @@ -1525,7 +1525,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json b/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json index 7082ad5ba961..e98602c66707 100644 --- a/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json +++ b/tools/perf/pmu-events/arch/x86/icelakex/icx-metrics.json @@ -1821,7 +1821,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/cache.json b/tools/perf/pmu-events/arch/x86/ivybridge/cache.json index 6ddc7d1c61d5..46570b522095 100644 --- a/tools/perf/pmu-events/arch/x86/ivybridge/cache.json +++ b/tools/perf/pmu-events/arch/x86/ivybridge/cache.json @@ -8,16 +8,16 @@ "UMask": "0x1" }, { - "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability", + "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers unavailability", "CounterMask": "1", "EventCode": "0x48", "EventName": "L1D_PEND_MISS.FB_FULL", - "PublicDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.", + "PublicDescription": "Cycles a demand request was blocked due to Fill Buffers unavailability.", "SampleAfterValue": "2000003", "UMask": "0x2" }, { - "BriefDescription": "L1D miss oustandings duration in cycles", + "BriefDescription": "L1D miss outstanding duration in cycles", "EventCode": "0x48", "EventName": "L1D_PEND_MISS.PENDING", "PublicDescription": "Increments the number of outstanding L1D misses every cycle. Set Cmask = 1 and Edge =1 to count occurrences.", @@ -506,7 +506,7 @@ "UMask": "0x8" }, { - "BriefDescription": "Cacheable and noncachaeble code read requests", + "BriefDescription": "Cacheable and noncacheable code read requests", "EventCode": "0xB0", "EventName": "OFFCORE_REQUESTS.DEMAND_CODE_RD", "PublicDescription": "Demand code read requests sent to uncore.", diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json b/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json index 87c958213c7a..89c6d47cc077 100644 --- a/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/ivybridge/floating-point.json @@ -73,7 +73,7 @@ "UMask": "0x20" }, { - "BriefDescription": "Number of FP Computational Uops Executed this cycle. The number of FADD, FSUB, FCOM, FMULs, integer MULsand IMULs, FDIVs, FPREMs, FSQRTS, integer DIVs, and IDIVs. This event does not distinguish an FADD used in the middle of a transcendental flow from a s", + "BriefDescription": "Number of FP Computational Uops Executed this cycle. The number of FADD, FSUB, FCOM, FMULs, integer MULs and IMULs, FDIVs, FPREMs, FSQRTS, integer DIVs, and IDIVs. This event does not distinguish an FADD used in the middle of a transcendental flow from a s", "EventCode": "0x10", "EventName": "FP_COMP_OPS_EXE.X87", "PublicDescription": "Counts number of X87 uops executed.", diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json b/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json index 89004a6c9ed1..4ee100024ca9 100644 --- a/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json +++ b/tools/perf/pmu-events/arch/x86/ivybridge/frontend.json @@ -142,35 +142,35 @@ "UMask": "0x4" }, { - "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy", + "BriefDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy", "CounterMask": "1", "EventCode": "0x79", "EventName": "IDQ.MS_CYCLES", - "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.", + "PublicDescription": "Cycles when uops are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy.", "SampleAfterValue": "2000003", "UMask": "0x30" }, { - "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy", + "BriefDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy", "CounterMask": "1", "EventCode": "0x79", "EventName": "IDQ.MS_DSB_CYCLES", - "PublicDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy.", + "PublicDescription": "Cycles when uops initiated by Decode Stream Buffer (DSB) are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy.", "SampleAfterValue": "2000003", "UMask": "0x10" }, { - "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy", + "BriefDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequencer (MS) is busy", "CounterMask": "1", "EdgeDetect": "1", "EventCode": "0x79", "EventName": "IDQ.MS_DSB_OCCUR", - "PublicDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequenser (MS) is busy.", + "PublicDescription": "Deliveries to Instruction Decode Queue (IDQ) initiated by Decode Stream Buffer (DSB) while Microcode Sequencer (MS) is busy.", "SampleAfterValue": "2000003", "UMask": "0x10" }, { - "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy", + "BriefDescription": "Uops initiated by Decode Stream Buffer (DSB) that are being delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy", "EventCode": "0x79", "EventName": "IDQ.MS_DSB_UOPS", "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by DSB. Set Cmask = 1 to count cycles. Add Edge=1 to count # of delivery.", @@ -178,7 +178,7 @@ "UMask": "0x10" }, { - "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy", + "BriefDescription": "Uops initiated by MITE and delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy", "EventCode": "0x79", "EventName": "IDQ.MS_MITE_UOPS", "PublicDescription": "Increment each cycle # of uops delivered to IDQ when MS_busy by MITE. Set Cmask = 1 to count cycles.", @@ -196,7 +196,7 @@ "UMask": "0x30" }, { - "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequenser (MS) is busy", + "BriefDescription": "Uops delivered to Instruction Decode Queue (IDQ) while Microcode Sequencer (MS) is busy", "EventCode": "0x79", "EventName": "IDQ.MS_UOPS", "PublicDescription": "Increment each cycle # of uops delivered to IDQ from MS by either DSB or MITE. Set Cmask = 1 to count cycles.", diff --git a/tools/perf/pmu-events/arch/x86/ivytown/cache.json b/tools/perf/pmu-events/arch/x86/ivytown/cache.json index c8f7d5e66504..0e8e77253978 100644 --- a/tools/perf/pmu-events/arch/x86/ivytown/cache.json +++ b/tools/perf/pmu-events/arch/x86/ivytown/cache.json @@ -8,11 +8,11 @@ "UMask": "0x1" }, { - "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability", + "BriefDescription": "Cycles a demand request was blocked due to Fill Buffers unavailability", "CounterMask": "1", "EventCode": "0x48", "EventName": "L1D_PEND_MISS.FB_FULL", - "PublicDescription": "Cycles a demand request was blocked due to Fill Buffers inavailability.", + "PublicDescription": "Cycles a demand request was blocked due to Fill Buffers unavailability.", "SampleAfterValue": "2000003", "UMask": "0x2" }, diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json index ccf451534d16..914d2cfb3d3d 100644 --- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json @@ -140,7 +140,7 @@ "EventCode": "0x4", "EventName": "UNC_I_RxR_BL_DRS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -148,21 +148,21 @@ "EventCode": "0x1", "EventName": "UNC_I_RxR_BL_DRS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x7", "EventName": "UNC_I_RxR_BL_DRS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x5", "EventName": "UNC_I_RxR_BL_NCB_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -170,21 +170,21 @@ "EventCode": "0x2", "EventName": "UNC_I_RxR_BL_NCB_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x8", "EventName": "UNC_I_RxR_BL_NCB_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x6", "EventName": "UNC_I_RxR_BL_NCS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -192,14 +192,14 @@ "EventCode": "0x3", "EventName": "UNC_I_RxR_BL_NCS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x9", "EventName": "UNC_I_RxR_BL_NCS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -293,7 +293,7 @@ "EventCode": "0xd", "EventName": "UNC_I_TxR_REQUEST_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumultes the number of outstanding outbound requests from the IRP to the switch (towards the devices). This can be used in conjuection with the allocations event in order to calculate average latency of outbound requests.", + "PublicDescription": "Accumulates the number of outstanding outbound requests from the IRP to the switch (towards the devices). This can be used in conjunction with the allocations event in order to calculate average latency of outbound requests.", "Unit": "IRP" }, { diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json index 874f15ea8228..0fc907e5cf3c 100644 --- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json +++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json @@ -140,7 +140,7 @@ "EventCode": "0x4", "EventName": "UNC_I_RxR_BL_DRS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -148,21 +148,21 @@ "EventCode": "0x1", "EventName": "UNC_I_RxR_BL_DRS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x7", "EventName": "UNC_I_RxR_BL_DRS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x5", "EventName": "UNC_I_RxR_BL_NCB_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -170,21 +170,21 @@ "EventCode": "0x2", "EventName": "UNC_I_RxR_BL_NCB_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x8", "EventName": "UNC_I_RxR_BL_NCB_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x6", "EventName": "UNC_I_RxR_BL_NCS_CYCLES_FULL", "PerPkg": "1", - "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of cycles when the BL Ingress is full. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { @@ -192,14 +192,14 @@ "EventCode": "0x3", "EventName": "UNC_I_RxR_BL_NCS_INSERTS", "PerPkg": "1", - "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Counts the number of allocations into the BL Ingress. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { "EventCode": "0x9", "EventName": "UNC_I_RxR_BL_NCS_OCCUPANCY", "PerPkg": "1", - "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requets as well as outbound MMIO writes.", + "PublicDescription": "Accumulates the occupancy of the BL Ingress in each cycles. This queue is where the IRP receives data from R2PCIe (the ring). It is used for data returns from read requests as well as outbound MMIO writes.", "Unit": "IRP" }, { diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/cache.json b/tools/perf/pmu-events/arch/x86/knightslanding/cache.json index d9876cb06b08..8da3a5a7be73 100644 --- a/tools/perf/pmu-events/arch/x86/knightslanding/cache.json +++ b/tools/perf/pmu-events/arch/x86/knightslanding/cache.json @@ -6,13 +6,19 @@ "SampleAfterValue": "200003" }, { - "BriefDescription": "Counts the number of core cycles the fetch stalls because of an icache miss. This is a cumulative count of core cycles the fetch stalled for all icache misses.", + "BriefDescription": "This event counts the number of core cycles the fetch stalls because of an icache miss. This is a cumulative count of cycles the NIP stalled for all icache misses.", "EventCode": "0x86", "EventName": "FETCH_STALL.ICACHE_FILL_PENDING_CYCLES", - "PublicDescription": "This event counts the number of core cycles the fetch stalls because of an icache miss. This is a cumulative count of cycles the NIP stalled for all icache misses.", "SampleAfterValue": "200003", "UMask": "0x4" }, + { + "BriefDescription": "Counts the number of L2HWP allocated into XQ GP", + "EventCode": "0x3E", + "EventName": "L2_PREFETCHER.ALLOC_XQ", + "SampleAfterValue": "100007", + "UMask": "0x4" + }, { "BriefDescription": "Counts the number of L2 cache misses", "EventCode": "0x2E", @@ -28,7 +34,7 @@ "UMask": "0x4f" }, { - "BriefDescription": "Counts the number of MEC requests from the L2Q that reference a cache line (cacheable requests) excluding SW prefetches filling only to L2 cache and L1 evictions (automatically exlcudes L2HWP, UC, WC) that were rejected - Multiple repeated rejects should be counted multiple times", + "BriefDescription": "Counts the number of MEC requests from the L2Q that reference a cache line (cacheable requests) excluding SW prefetches filling only to L2 cache and L1 evictions (automatically excludes L2HWP, UC, WC) that were rejected - Multiple repeated rejects should be counted multiple times", "EventCode": "0x30", "EventName": "L2_REQUESTS_REJECT.ALL", "SampleAfterValue": "200003" @@ -50,11 +56,12 @@ "UMask": "0x80" }, { - "BriefDescription": "Counts the loads retired that get the data from the other core in the same tile in M state", + "BriefDescription": "Counts the loads retired that get the data from the other core in the same tile in M state (Precise Event)", "Data_LA": "1", "EventCode": "0x04", "EventName": "MEM_UOPS_RETIRED.HITM", "PEBS": "1", + "PublicDescription": "This event counts the number of load micro-ops retired that got data from another core's cache. (Precise Event).", "SampleAfterValue": "200003", "UMask": "0x20" }, @@ -67,20 +74,22 @@ "UMask": "0x1" }, { - "BriefDescription": "Counts the number of load micro-ops retired that hit in the L2", + "BriefDescription": "Counts the number of load micro-ops retired that hit in the L2 (Precise Event)", "Data_LA": "1", "EventCode": "0x04", "EventName": "MEM_UOPS_RETIRED.L2_HIT_LOADS", "PEBS": "1", + "PublicDescription": "This event counts the number of load micro-uops retired that hit in the L2 (Precise Event)", "SampleAfterValue": "200003", "UMask": "0x2" }, { - "BriefDescription": "Counts the number of load micro-ops retired that miss in the L2", + "BriefDescription": "Counts the number of load micro-ops retired that miss in the L2 (Precise Event)", "Data_LA": "1", "EventCode": "0x04", "EventName": "MEM_UOPS_RETIRED.L2_MISS_LOADS", "PEBS": "1", + "PublicDescription": "This event counts the number of load micro-ops retired that miss in the L2 (Precise Event)", "SampleAfterValue": "100007", "UMask": "0x4" }, @@ -620,6 +629,15 @@ "SampleAfterValue": "100007", "UMask": "0x1" }, + { + "BriefDescription": "Accounts for responses which miss its own tile's L2.", + "EventCode": "0xB7", + "EventName": "OFFCORE_RESPONSE.ANY_REQUEST.L2_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x18001981F8", + "SampleAfterValue": "100007", + "UMask": "0x1" + }, { "BriefDescription": "Counts any request that are outstanding, per weighted cycle, from the time of the request to when any response is received. The outstanding response should be programmed only on PMC0.", "EventCode": "0xB7", @@ -1664,15 +1682,6 @@ "SampleAfterValue": "100007", "UMask": "0x1" }, - { - "BriefDescription": "Counts L2 data RFO prefetches (includes PREFETCHW instruction) that provides no supplier details", - "EventCode": "0xB7", - "EventName": "OFFCORE_RESPONSE.PF_L2_RFO.SUPPLIER_NONE", - "MSRIndex": "0x1a6,0x1a7", - "MSRValue": "0x0000020020", - "SampleAfterValue": "100007", - "UMask": "0x1" - }, { "BriefDescription": "Counts Software Prefetches that accounts for any response", "EventCode": "0xB7", diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/floating-point.json b/tools/perf/pmu-events/arch/x86/knightslanding/floating-point.json index ecc96f32f167..089aa3ef345d 100644 --- a/tools/perf/pmu-events/arch/x86/knightslanding/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/knightslanding/floating-point.json @@ -8,18 +8,18 @@ "UMask": "0x4" }, { - "BriefDescription": "Counts the number of vector SSE, AVX, AVX2, AVX-512 micro-ops retired. More specifically, it counts packed SSE, AVX, AVX2, AVX-512 micro-ops (both floating point and integer) except for loads (memory-to-register mov-type micro-ops), packed byte and word multiplies.", + "BriefDescription": "Counts the number of packed SSE, AVX, AVX2, AVX-512 micro-ops (both floating point and integer) except for loads (memory-to-register mov-type micro-ops), packed byte and word multiplies.", "EventCode": "0xC2", "EventName": "UOPS_RETIRED.PACKED_SIMD", - "PublicDescription": "This event counts the number of packed vector SSE, AVX, AVX2, and AVX-512 micro-ops retired (floating point, integer and store) except for loads (memory-to-register mov-type micro-ops), packed byte and word multiplies.", + "PublicDescription": "The length of the packed operation (128bits, 256bits or 512bits) is not taken into account when updating the counter; all count the same (+1). \r\nMask (k) registers are ignored. For example: a micro-op operating with a mask that only enables one element or even zero elements will still trigger this counter (+1)\r\nThis event is defined at the micro-op level and not instruction level. Most instructions are implemented with one micro-op but not all.", "SampleAfterValue": "200003", "UMask": "0x40" }, { - "BriefDescription": "Counts the number of scalar SSE, AVX, AVX2, AVX-512 micro-ops retired. More specifically, it counts scalar SSE, AVX, AVX2, AVX-512 micro-ops except for loads (memory-to-register mov-type micro ops), division, sqrt.", + "BriefDescription": "Counts the number of scalar SSE, AVX, AVX2, AVX-512 micro-ops except for loads (memory-to-register mov-type micro ops), division, sqrt.", "EventCode": "0xC2", "EventName": "UOPS_RETIRED.SCALAR_SIMD", - "PublicDescription": "This event counts the number of scalar SSE, AVX, AVX2, AVX-512 micro-ops retired (floating point, integer and store) except for loads (memory-to-register mov-type micro ops), division, sqrt.", + "PublicDescription": "This event is defined at the micro-op level and not instruction level. Most instructions are implemented with one micro-op but not all.", "SampleAfterValue": "200003", "UMask": "0x20" } diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json b/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json index 3dc532107ead..5b2e71750976 100644 --- a/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/knightslanding/pipeline.json @@ -1,13 +1,13 @@ [ { - "BriefDescription": "Counts the number of branch instructions retired", + "BriefDescription": "Counts the number of branch instructions retired (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.ALL_BRANCHES", "PEBS": "1", "SampleAfterValue": "200003" }, { - "BriefDescription": "Counts the number of near CALL branch instructions retired.", + "BriefDescription": "Counts the number of near CALL branch instructions retired. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.CALL", "PEBS": "1", @@ -15,7 +15,7 @@ "UMask": "0xf9" }, { - "BriefDescription": "Counts the number of far branch instructions retired.", + "BriefDescription": "Counts the number of far branch instructions retired. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.FAR_BRANCH", "PEBS": "1", @@ -23,7 +23,7 @@ "UMask": "0xbf" }, { - "BriefDescription": "Counts the number of near indirect CALL branch instructions retired.", + "BriefDescription": "Counts the number of near indirect CALL branch instructions retired. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.IND_CALL", "PEBS": "1", @@ -31,7 +31,7 @@ "UMask": "0xfb" }, { - "BriefDescription": "Counts the number of branch instructions retired that were conditional jumps.", + "BriefDescription": "Counts the number of branch instructions retired that were conditional jumps. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.JCC", "PEBS": "1", @@ -39,7 +39,7 @@ "UMask": "0x7e" }, { - "BriefDescription": "Counts the number of branch instructions retired that were near indirect CALL or near indirect JMP.", + "BriefDescription": "Counts the number of branch instructions retired that were near indirect CALL or near indirect JMP. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.NON_RETURN_IND", "PEBS": "1", @@ -47,7 +47,7 @@ "UMask": "0xeb" }, { - "BriefDescription": "Counts the number of near relative CALL branch instructions retired.", + "BriefDescription": "Counts the number of near relative CALL branch instructions retired. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.REL_CALL", "PEBS": "1", @@ -55,7 +55,7 @@ "UMask": "0xfd" }, { - "BriefDescription": "Counts the number of near RET branch instructions retired.", + "BriefDescription": "Counts the number of near RET branch instructions retired. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.RETURN", "PEBS": "1", @@ -63,7 +63,7 @@ "UMask": "0xf7" }, { - "BriefDescription": "Counts the number of branch instructions retired that were conditional jumps and predicted taken.", + "BriefDescription": "Counts the number of branch instructions retired that were conditional jumps and predicted taken. (Precise Event)", "EventCode": "0xC4", "EventName": "BR_INST_RETIRED.TAKEN_JCC", "PEBS": "1", @@ -71,14 +71,14 @@ "UMask": "0xfe" }, { - "BriefDescription": "Counts the number of mispredicted branch instructions retired", + "BriefDescription": "Counts the number of mispredicted branch instructions retired (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.ALL_BRANCHES", "PEBS": "1", "SampleAfterValue": "200003" }, { - "BriefDescription": "Counts the number of mispredicted near CALL branch instructions retired.", + "BriefDescription": "Counts the number of mispredicted near CALL branch instructions retired. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.CALL", "PEBS": "1", @@ -86,7 +86,7 @@ "UMask": "0xf9" }, { - "BriefDescription": "Counts the number of mispredicted far branch instructions retired.", + "BriefDescription": "Counts the number of mispredicted far branch instructions retired. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.FAR_BRANCH", "PEBS": "1", @@ -94,7 +94,7 @@ "UMask": "0xbf" }, { - "BriefDescription": "Counts the number of mispredicted near indirect CALL branch instructions retired.", + "BriefDescription": "Counts the number of mispredicted near indirect CALL branch instructions retired. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.IND_CALL", "PEBS": "1", @@ -102,7 +102,7 @@ "UMask": "0xfb" }, { - "BriefDescription": "Counts the number of mispredicted branch instructions retired that were conditional jumps.", + "BriefDescription": "Counts the number of mispredicted branch instructions retired that were conditional jumps. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.JCC", "PEBS": "1", @@ -110,7 +110,7 @@ "UMask": "0x7e" }, { - "BriefDescription": "Counts the number of mispredicted branch instructions retired that were near indirect CALL or near indirect JMP.", + "BriefDescription": "Counts the number of mispredicted branch instructions retired that were near indirect CALL or near indirect JMP. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.NON_RETURN_IND", "PEBS": "1", @@ -118,7 +118,7 @@ "UMask": "0xeb" }, { - "BriefDescription": "Counts the number of mispredicted near relative CALL branch instructions retired.", + "BriefDescription": "Counts the number of mispredicted near relative CALL branch instructions retired. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.REL_CALL", "PEBS": "1", @@ -126,7 +126,7 @@ "UMask": "0xfd" }, { - "BriefDescription": "Counts the number of mispredicted near RET branch instructions retired.", + "BriefDescription": "Counts the number of mispredicted near RET branch instructions retired. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.RETURN", "PEBS": "1", @@ -134,7 +134,7 @@ "UMask": "0xf7" }, { - "BriefDescription": "Counts the number of mispredicted branch instructions retired that were conditional jumps and predicted taken.", + "BriefDescription": "Counts the number of mispredicted branch instructions retired that were conditional jumps and predicted taken. (Precise Event)", "EventCode": "0xC5", "EventName": "BR_MISP_RETIRED.TAKEN_JCC", "PEBS": "1", @@ -189,7 +189,14 @@ "SampleAfterValue": "2000003" }, { - "BriefDescription": "Counts all nukes", + "BriefDescription": "Counts the number of instructions retired (Precise Event)", + "EventCode": "0xC0", + "EventName": "INST_RETIRED.ANY_PS", + "PEBS": "2", + "SampleAfterValue": "2000003" + }, + { + "BriefDescription": "Counts all machine clears", "EventCode": "0xC3", "EventName": "MACHINE_CLEARS.ALL", "SampleAfterValue": "200003", @@ -261,20 +268,22 @@ "UMask": "0x2" }, { - "BriefDescription": "Counts the number of occurrences a retired load gets blocked because its address partially overlaps with a store", + "BriefDescription": "Counts the number of occurrences a retired load gets blocked because its address partially overlaps with a store (Precise Event)", "Data_LA": "1", "EventCode": "0x03", "EventName": "RECYCLEQ.LD_BLOCK_ST_FORWARD", "PEBS": "1", + "PublicDescription": "This event counts the number of retired loads that were prohibited from receiving forwarded data from a previous store because of address mismatch.", "SampleAfterValue": "200003", "UMask": "0x1" }, { - "BriefDescription": "Counts the number of occurrences a retired load that is a cache line split. Each split should be counted only once.", + "BriefDescription": "Counts the number of occurrences a retired load was pushed into the rehab queue because it sees a cache line split. Each split should be counted only once. (Precise Event)", "Data_LA": "1", "EventCode": "0x03", "EventName": "RECYCLEQ.LD_SPLITS", "PEBS": "1", + "PublicDescription": "This event counts the number of retired loads which was pushed into the recycled queue that experienced cache line boundary splits (Precise event). Not that each split should be counted only once.", "SampleAfterValue": "200003", "UMask": "0x8" }, @@ -286,7 +295,7 @@ "UMask": "0x10" }, { - "BriefDescription": "Counts the store micro-ops retired that were pushed in the rehad queue because the store address buffer is full", + "BriefDescription": "Counts the store micro-ops retired that were pushed in the rehab queue because the store address buffer is full", "EventCode": "0x03", "EventName": "RECYCLEQ.STA_FULL", "SampleAfterValue": "200003", @@ -301,7 +310,7 @@ "UMask": "0x4" }, { - "BriefDescription": "Counts the total number of core cycles the Alloc pipeline is stalled when any one of the reservation stations is full.", + "BriefDescription": "Counts the total number of core cycles allocation pipeline is stalled when any one of the reservation stations is full.", "EventCode": "0xCB", "EventName": "RS_FULL_STALL.ALL", "SampleAfterValue": "200003", diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/uncore-cache.json b/tools/perf/pmu-events/arch/x86/knightslanding/uncore-cache.json index 1b8dcfa5461c..120e4813d82a 100644 --- a/tools/perf/pmu-events/arch/x86/knightslanding/uncore-cache.json +++ b/tools/perf/pmu-events/arch/x86/knightslanding/uncore-cache.json @@ -2558,7 +2558,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.AD_REQ_VN0", "PerPkg": "1", @@ -2566,7 +2566,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.AD_RSP_VN0", "PerPkg": "1", @@ -2574,7 +2574,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.AK_NON_UPI", "PerPkg": "1", @@ -2582,7 +2582,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.BL_NCB_VN0", "PerPkg": "1", @@ -2590,7 +2590,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.BL_NCS_VN0", "PerPkg": "1", @@ -2598,7 +2598,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.BL_RSP_VN0", "PerPkg": "1", @@ -2606,7 +2606,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.BL_WB_VN0", "PerPkg": "1", @@ -2614,7 +2614,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2A", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q0_RETRY.IV_NON_UPI", "PerPkg": "1", @@ -2622,7 +2622,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2B", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q1_RETRY.ALLOW_SNP", "PerPkg": "1", @@ -2630,7 +2630,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2B", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q1_RETRY.ANY_REJECT_IRQ0", "PerPkg": "1", @@ -2638,7 +2638,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2B", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q1_RETRY.PA_MATCH", "PerPkg": "1", @@ -2646,7 +2646,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2B", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q1_RETRY.SF_VICTIM", "PerPkg": "1", @@ -2654,7 +2654,7 @@ "Unit": "CHA" }, { - "BriefDescription": "REQUESTQ'' includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", + "BriefDescription": "REQUESTQ includes: IRQ, PRQ, IPQ, RRQ, WBQ (everything except for ISMQ)", "EventCode": "0x2B", "EventName": "UNC_H_INGRESS_RETRY_REQ_Q1_RETRY.SF_WAY", "PerPkg": "1", diff --git a/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json b/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json index 99a8fa8f19cc..9be30a33b43b 100644 --- a/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json +++ b/tools/perf/pmu-events/arch/x86/knightslanding/virtual-memory.json @@ -1,6 +1,6 @@ [ { - "BriefDescription": "Counts the number of load micro-ops retired that cause a DTLB miss", + "BriefDescription": "Counts the number of load micro-ops retired that cause a DTLB miss (Precise Event)", "Data_LA": "1", "EventCode": "0x04", "EventName": "MEM_UOPS_RETIRED.DTLB_MISS_LOADS", diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/cache.json b/tools/perf/pmu-events/arch/x86/lunarlake/cache.json new file mode 100644 index 000000000000..1823149067b5 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/lunarlake/cache.json @@ -0,0 +1,219 @@ +[ + { + "BriefDescription": "Counts the number of L2 Cache Accesses Counts the total number of L2 Cache Accesses - sum of hits, misses, rejects front door requests for CRd/DRd/RFO/ItoM/L2 Prefetches only, per core event", + "EventCode": "0x24", + "EventName": "L2_REQUEST.ALL", + "PublicDescription": "Counts the number of L2 Cache Accesses Counts the total number of L2 Cache Accesses - sum of hits, misses, rejects front door requests for CRd/DRd/RFO/ItoM/L2 Prefetches only.", + "SampleAfterValue": "1000003", + "UMask": "0x7", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.MISS", + "PublicDescription": "Counts the number of cacheable memory requests that miss in the Last Level Cache (LLC). Requests include demand loads, reads for ownership (RFO), instruction fetches and L1 HW prefetches. If the platform has an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.", + "SampleAfterValue": "200003", + "UMask": "0x41", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Core-originated cacheable requests that missed L3 (Except hardware prefetches to the L3)", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.MISS", + "PublicDescription": "Counts core-originated cacheable requests that miss the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches to the L1 and L2. It does not include hardware prefetches to the L3, and may not count other types of requests to the L3.", + "SampleAfterValue": "100003", + "UMask": "0x41", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of cacheable memory requests that access the LLC. Counts on a per core basis.", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.REFERENCE", + "PublicDescription": "Counts the number of cacheable memory requests that access the Last Level Cache (LLC). Requests include demand loads, reads for ownership (RFO), instruction fetches and L1 HW prefetches. If the platform has an L3 cache, the LLC is the L3 cache, otherwise it is the L2 cache. Counts on a per core basis.", + "SampleAfterValue": "1000003", + "UMask": "0x4f", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Core-originated cacheable requests that refer to L3 (Except hardware prefetches to the L3)", + "EventCode": "0x2e", + "EventName": "LONGEST_LAT_CACHE.REFERENCE", + "PublicDescription": "Counts core-originated cacheable requests to the L3 cache (Longest Latency cache). Requests include data and code reads, Reads-for-Ownership (RFOs), speculative accesses and hardware prefetches to the L1 and L2. It does not include hardware prefetches to the L3, and may not count other types of requests to the L3.", + "SampleAfterValue": "100003", + "UMask": "0x4f", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Retired load instructions.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.ALL_LOADS", + "PEBS": "1", + "PublicDescription": "Counts all retired load instructions. This event accounts for SW prefetch instructions of PREFETCHNTA or PREFETCHT0/1/2 or PREFETCHW.", + "SampleAfterValue": "1000003", + "UMask": "0x81", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Retired store instructions.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_INST_RETIRED.ALL_STORES", + "PEBS": "1", + "PublicDescription": "Counts all retired store instructions.", + "SampleAfterValue": "1000003", + "UMask": "0x82", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of load uops retired.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL_LOADS", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0x81", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of store uops retired.", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.ALL_STORES", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0x82", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024", + "MSRIndex": "0x3F6", + "MSRValue": "0x400", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128", + "MSRIndex": "0x3F6", + "MSRValue": "0x80", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16", + "MSRIndex": "0x3F6", + "MSRValue": "0x10", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048", + "MSRIndex": "0x3F6", + "MSRValue": "0x800", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256", + "MSRIndex": "0x3F6", + "MSRValue": "0x100", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32", + "MSRIndex": "0x3F6", + "MSRValue": "0x20", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4", + "MSRIndex": "0x3F6", + "MSRValue": "0x4", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512", + "MSRIndex": "0x3F6", + "MSRValue": "0x200", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64", + "MSRIndex": "0x3F6", + "MSRValue": "0x40", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8", + "MSRIndex": "0x3F6", + "MSRValue": "0x8", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES", + "Data_LA": "1", + "EventCode": "0xd0", + "EventName": "MEM_UOPS_RETIRED.STORE_LATENCY", + "PEBS": "2", + "SampleAfterValue": "1000003", + "UMask": "0x6", + "Unit": "cpu_atom" + } +] diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/frontend.json b/tools/perf/pmu-events/arch/x86/lunarlake/frontend.json new file mode 100644 index 000000000000..5e4ef81b43d6 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/lunarlake/frontend.json @@ -0,0 +1,27 @@ +[ + { + "BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump.", + "EventCode": "0x80", + "EventName": "ICACHE.ACCESSES", + "SampleAfterValue": "200003", + "UMask": "0x3", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump and the instruction cache registers bytes are not present. -", + "EventCode": "0x80", + "EventName": "ICACHE.MISSES", + "SampleAfterValue": "200003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "This event counts a subset of the Topdown Slots event that were no operation was delivered to the back-end pipeline due to instruction fetch limitations when the back-end could have accepted more operations. Common examples include instruction cache misses or x86 instruction decode limitations.", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CORE", + "PublicDescription": "This event counts a subset of the Topdown Slots event that were no operation was delivered to the back-end pipeline due to instruction fetch limitations when the back-end could have accepted more operations. Common examples include instruction cache misses or x86 instruction decode limitations.\nSoftware can use this event as the numerator for the Frontend Bound metric (or top-level category) of the Top-down Microarchitecture Analysis method.", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_core" + } +] diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/memory.json b/tools/perf/pmu-events/arch/x86/lunarlake/memory.json new file mode 100644 index 000000000000..51d70ba00bd4 --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/lunarlake/memory.json @@ -0,0 +1,183 @@ +[ + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 1024 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_1024", + "MSRIndex": "0x3F6", + "MSRValue": "0x400", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 1024 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "53", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_128", + "MSRIndex": "0x3F6", + "MSRValue": "0x80", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 128 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "1009", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_16", + "MSRIndex": "0x3F6", + "MSRValue": "0x10", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 16 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "20011", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 2048 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_2048", + "MSRIndex": "0x3F6", + "MSRValue": "0x800", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 2048 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "23", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_256", + "MSRIndex": "0x3F6", + "MSRValue": "0x100", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 256 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "503", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_32", + "MSRIndex": "0x3F6", + "MSRValue": "0x20", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 32 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "100007", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_4", + "MSRIndex": "0x3F6", + "MSRValue": "0x4", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 4 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_512", + "MSRIndex": "0x3F6", + "MSRValue": "0x200", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 512 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "101", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_64", + "MSRIndex": "0x3F6", + "MSRValue": "0x40", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 64 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "2003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.LOAD_LATENCY_GT_8", + "MSRIndex": "0x3F6", + "MSRValue": "0x8", + "PEBS": "2", + "PublicDescription": "Counts randomly selected loads when the latency from first dispatch to completion is greater than 8 cycles. Reported latency may be longer than just the memory latency.", + "SampleAfterValue": "50021", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Retired memory store access operations. A PDist event for PEBS Store Latency Facility.", + "Data_LA": "1", + "EventCode": "0xcd", + "EventName": "MEM_TRANS_RETIRED.STORE_SAMPLE", + "PEBS": "2", + "PublicDescription": "Counts Retired memory accesses with at least 1 store operation. This PEBS event is the precisely-distributed (PDist) trigger covering all stores uops for sampling by the PEBS Store Latency Facility. The facility is described in Intel SDM Volume 3 section 19.9.8", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts cacheable demand data reads were not supplied by the L3 cache.", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_DATA_RD.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts demand reads for ownership, including SWPREFETCHW which is an RFO were not supplied by the L3 cache.", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_RFO.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + } +] diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/other.json b/tools/perf/pmu-events/arch/x86/lunarlake/other.json new file mode 100644 index 000000000000..69adaed5686d --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/lunarlake/other.json @@ -0,0 +1,62 @@ +[ + { + "BriefDescription": "Counts cacheable demand data reads Catch all value for any response types - this includes response types not define in the OCR. If this is set all other response types will be ignored", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts demand data reads that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts cacheable demand data reads were supplied by DRAM.", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_DATA_RD.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x184000001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x184000001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts demand reads for ownership, including SWPREFETCHW which is an RFO Catch all value for any response types - this includes response types not define in the OCR. If this is set all other response types will be ignored", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + } +] diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json b/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json new file mode 100644 index 000000000000..2bde664fdc0f --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/lunarlake/pipeline.json @@ -0,0 +1,217 @@ +[ + { + "BriefDescription": "Counts the total number of branch instructions retired for all branch types.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.ALL_BRANCHES", + "PEBS": "1", + "PublicDescription": "Counts the total number of instructions in which the instruction pointer (IP) of the processor is resteered due to a branch instruction and the branch instruction successfully retires. All branch type instructions are accounted for.", + "SampleAfterValue": "200003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "All branch instructions retired.", + "EventCode": "0xc4", + "EventName": "BR_INST_RETIRED.ALL_BRANCHES", + "PEBS": "1", + "PublicDescription": "Counts all branch instructions retired.", + "SampleAfterValue": "400009", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.ALL_BRANCHES", + "PEBS": "1", + "PublicDescription": "Counts the total number of mispredicted branch instructions retired. All branch type instructions are accounted for. Prediction of the branch target address enables the processor to begin executing instructions before the non-speculative execution path is known. The branch prediction unit (BPU) predicts the target address based on the instruction pointer (IP) of the branch and on the execution path through which execution reached this IP. A branch misprediction occurs when the prediction is wrong, and results in discarding all instructions executed in the speculative path and re-fetching from the correct path.", + "SampleAfterValue": "200003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "All mispredicted branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.ALL_BRANCHES", + "PEBS": "1", + "PublicDescription": "Counts all the retired branch instructions that were mispredicted by the processor. A branch misprediction occurs when the processor incorrectly predicts the destination of the branch. When the misprediction is discovered at execution, all the instructions executed in the wrong (speculative) path must be discarded, and the processor must start fetching from the correct path.", + "SampleAfterValue": "400009", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles", + "EventName": "CPU_CLK_UNHALTED.CORE", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of unhalted core clock cycles [This event is alias to CPU_CLK_UNHALTED.THREAD_P]", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.CORE_P", + "SampleAfterValue": "2000003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of unhalted reference clock cycles", + "EventName": "CPU_CLK_UNHALTED.REF_TSC", + "SampleAfterValue": "1000003", + "UMask": "0x3", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Reference cycles when the core is not in halt state.", + "EventName": "CPU_CLK_UNHALTED.REF_TSC", + "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.", + "SampleAfterValue": "2000003", + "UMask": "0x3", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Reference cycles when the core is not in halt state.", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.REF_TSC_P", + "PublicDescription": "Counts the number of reference cycles when the core is not in a halt state. The core enters the halt state when it is running the HLT instruction or the MWAIT instruction. This event is not affected by core frequency changes (for example, P states, TM2 transitions) but has the same incrementing frequency as the time stamp counter. This event can approximate elapsed time while the core was not in a halt state. Note: On all current platforms this event stops counting during 'throttling (TM)' states duty off periods the processor is 'halted'. The counter update is done at a lower clock rate then the core clock the overflow status bit for this counter may appear 'sticky'. After the counter has overflowed and software clears the overflow status bit and resets the counter to less than MAX. The reset value to the counter is not clocked immediately so the overflow status bit will flip 'high (1)' and generate another PMI (if enabled) after which the reset value gets clocked into the counter. Therefore, software will get the interrupt, read the overflow status bit '1 for bit 34 while the counter value is less than MAX. Software should ignore this case.", + "SampleAfterValue": "2000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Core cycles when the thread is not in halt state", + "EventName": "CPU_CLK_UNHALTED.THREAD", + "PublicDescription": "Counts the number of core cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. This event is a component in many key event ratios. The core frequency may change from time to time due to transitions associated with Enhanced Intel SpeedStep Technology or TM2. For this reason this event may have a changing ratio with regards to time. When the core frequency is constant, this event can approximate elapsed time while the core was not in the halt state. It is counted on a dedicated fixed counter, leaving the eight programmable counters available for other events.", + "SampleAfterValue": "2000003", + "UMask": "0x2", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of unhalted core clock cycles [This event is alias to CPU_CLK_UNHALTED.CORE_P]", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.THREAD_P", + "SampleAfterValue": "2000003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Thread cycles when thread is not in halt state", + "EventCode": "0x3c", + "EventName": "CPU_CLK_UNHALTED.THREAD_P", + "PublicDescription": "This is an architectural event that counts the number of thread cycles while the thread is not in a halt state. The thread enters the halt state when it is running the HLT instruction. The core frequency may change from time to time due to power or thermal throttling. For this reason, this event may have a changing ratio with regards to wall clock time.", + "SampleAfterValue": "2000003", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of instructions retired", + "EventName": "INST_RETIRED.ANY", + "PEBS": "1", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Number of instructions retired. Fixed Counter - architectural event", + "EventName": "INST_RETIRED.ANY", + "PEBS": "1", + "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.", + "SampleAfterValue": "2000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of instructions retired", + "EventCode": "0xc0", + "EventName": "INST_RETIRED.ANY_P", + "PEBS": "1", + "SampleAfterValue": "2000003", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Number of instructions retired. General Counter - architectural event", + "EventCode": "0xc0", + "EventName": "INST_RETIRED.ANY_P", + "PEBS": "1", + "PublicDescription": "Counts the number of X86 instructions retired - an Architectural PerfMon event. Counting continues during hardware interrupts, traps, and inside interrupt handlers. Notes: INST_RETIRED.ANY is counted by a designated fixed counter freeing up programmable counters to count other events. INST_RETIRED.ANY_P is counted by a programmable counter.", + "SampleAfterValue": "2000003", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of occurrences a retired load gets blocked because its address partially overlaps with an older store (size mismatch) - unknown_sta/bad_forward", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.STORE_FORWARD", + "PEBS": "1", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Loads blocked due to overlapping with a preceding store that cannot be forwarded.", + "EventCode": "0x03", + "EventName": "LD_BLOCKS.STORE_FORWARD", + "PublicDescription": "Counts the number of times where store forwarding was prevented for a load operation. The most common case is a load blocked due to the address of memory access (partially) overlapping with a preceding uncompleted store. Note: See the table of not supported store forwards in the Optimization Guide.", + "SampleAfterValue": "100003", + "UMask": "0x82", + "Unit": "cpu_core" + }, + { + "BriefDescription": "This event counts a subset of the Topdown Slots event that were not consumed by the back-end pipeline due to lack of back-end resources, as a result of memory subsystem delays, execution units limitations, or other conditions.", + "EventCode": "0xa4", + "EventName": "TOPDOWN.BACKEND_BOUND_SLOTS", + "PublicDescription": "This event counts a subset of the Topdown Slots event that were not consumed by the back-end pipeline due to lack of back-end resources, as a result of memory subsystem delays, execution units limitations, or other conditions.\nSoftware can use this event as the numerator for the Backend Bound metric (or top-level category) of the Top-down Microarchitecture Analysis method.", + "SampleAfterValue": "10000003", + "UMask": "0x2", + "Unit": "cpu_core" + }, + { + "BriefDescription": "TMA slots available for an unhalted logical processor. Fixed counter - architectural event", + "EventName": "TOPDOWN.SLOTS", + "PublicDescription": "Number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method (TMA). Software can use this event as the denominator for the top-level metrics of the TMA method. This architectural event is counted on a designated fixed counter (Fixed Counter 3).", + "SampleAfterValue": "10000003", + "UMask": "0x4", + "Unit": "cpu_core" + }, + { + "BriefDescription": "TMA slots available for an unhalted logical processor. General counter - architectural event", + "EventCode": "0xa4", + "EventName": "TOPDOWN.SLOTS_P", + "PublicDescription": "Counts the number of available slots for an unhalted logical processor. The event increments by machine-width of the narrowest pipeline as employed by the Top-down Microarchitecture Analysis method.", + "SampleAfterValue": "10000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear.", + "EventName": "TOPDOWN_BAD_SPECULATION.ALL", + "PublicDescription": "Fixed Counter: Counts the number of issue slots that were not consumed by the backend because allocation is stalled due to a mispredicted jump or a machine clear. Counts all issue slots blocked during this recovery window including relevant microcode flows and while uops are not yet available in the IQ. Also, includes the issue slots that were consumed by the backend but were thrown away because they were younger than the mispredict or machine clear.", + "SampleAfterValue": "1000003", + "UMask": "0x5", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of retirement slots not consumed due to backend stalls", + "EventCode": "0xa4", + "EventName": "TOPDOWN_BE_BOUND.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of retirement slots not consumed due to front end stalls", + "EventName": "TOPDOWN_FE_BOUND.ALL", + "SampleAfterValue": "1000003", + "UMask": "0x6", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Fixed Counter: Counts the number of consumed retirement slots. Similar to UOPS_RETIRED.ALL", + "EventName": "TOPDOWN_RETIRING.ALL", + "PEBS": "1", + "SampleAfterValue": "1000003", + "UMask": "0x7", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "This event counts a subset of the Topdown Slots event that are utilized by operations that eventually get retired (committed) by the processor pipeline. Usually, this event positively correlates with higher performance for example, as measured by the instructions-per-cycle metric.", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.SLOTS", + "PublicDescription": "This event counts a subset of the Topdown Slots event that are utilized by operations that eventually get retired (committed) by the processor pipeline. Usually, this event positively correlates with higher performance for example, as measured by the instructions-per-cycle metric.\nSoftware can use this event as the numerator for the Retiring metric (or top-level category) of the Top-down Microarchitecture Analysis method.", + "SampleAfterValue": "2000003", + "UMask": "0x2", + "Unit": "cpu_core" + } +] diff --git a/tools/perf/pmu-events/arch/x86/lunarlake/virtual-memory.json b/tools/perf/pmu-events/arch/x86/lunarlake/virtual-memory.json new file mode 100644 index 000000000000..bb9458799f1c --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/lunarlake/virtual-memory.json @@ -0,0 +1,56 @@ +[ + { + "BriefDescription": "Counts the number of page walks completed due to load DTLB misses to any page size.", + "EventCode": "0x08", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts the number of page walks completed due to loads (including SW prefetches) whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.", + "SampleAfterValue": "200003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Load miss in all TLB levels causes a page walk that completes. (All page sizes)", + "EventCode": "0x12", + "EventName": "DTLB_LOAD_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data loads. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0xe", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of page walks completed due to store DTLB misses to any page size.", + "EventCode": "0x49", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts the number of page walks completed due to stores whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.", + "SampleAfterValue": "2000003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Store misses in all TLB levels causes a page walk that completes. (All page sizes)", + "EventCode": "0x13", + "EventName": "DTLB_STORE_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts completed page walks (all page sizes) caused by demand data stores. This implies it missed in the DTLB and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0xe", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts the number of page walks completed due to instruction fetch misses to any page size.", + "EventCode": "0x85", + "EventName": "ITLB_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts the number of page walks completed due to instruction fetches whose address translations missed in all Translation Lookaside Buffer (TLB) levels and were mapped to any page size. Includes page walks that page fault.", + "SampleAfterValue": "2000003", + "UMask": "0xe", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Code miss in all TLB levels causes a page walk that completes. (All page sizes)", + "EventCode": "0x11", + "EventName": "ITLB_MISSES.WALK_COMPLETED", + "PublicDescription": "Counts completed page walks (all page sizes) caused by a code fetch. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB. The page walk can end with or without a fault.", + "SampleAfterValue": "100003", + "UMask": "0xe", + "Unit": "cpu_core" + } +] diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv index 3a8770e29fe8..e571683f59f3 100644 --- a/tools/perf/pmu-events/arch/x86/mapfile.csv +++ b/tools/perf/pmu-events/arch/x86/mapfile.csv @@ -1,39 +1,41 @@ Family-model,Version,Filename,EventType -GenuineIntel-6-(97|9A|B7|BA|BF),v1.21,alderlake,core -GenuineIntel-6-BE,v1.21,alderlaken,core -GenuineIntel-6-(1C|26|27|35|36),v4,bonnell,core +GenuineIntel-6-(97|9A|B7|BA|BF),v1.23,alderlake,core +GenuineIntel-6-BE,v1.23,alderlaken,core +GenuineIntel-6-(1C|26|27|35|36),v5,bonnell,core GenuineIntel-6-(3D|47),v28,broadwell,core -GenuineIntel-6-56,v10,broadwellde,core -GenuineIntel-6-4F,v21,broadwellx,core -GenuineIntel-6-55-[56789ABCDEF],v1.19,cascadelakex,core +GenuineIntel-6-56,v11,broadwellde,core +GenuineIntel-6-4F,v22,broadwellx,core +GenuineIntel-6-55-[56789ABCDEF],v1.20,cascadelakex,core GenuineIntel-6-9[6C],v1.04,elkhartlake,core +GenuineIntel-6-CF,v1.01,emeraldrapids,core GenuineIntel-6-5[CF],v13,goldmont,core GenuineIntel-6-7A,v1.01,goldmontplus,core GenuineIntel-6-B6,v1.00,grandridge,core GenuineIntel-6-A[DE],v1.01,graniterapids,core GenuineIntel-6-(3C|45|46),v33,haswell,core -GenuineIntel-6-3F,v27,haswellx,core +GenuineIntel-6-3F,v28,haswellx,core GenuineIntel-6-7[DE],v1.19,icelake,core GenuineIntel-6-6[AC],v1.21,icelakex,core GenuineIntel-6-3A,v24,ivybridge,core -GenuineIntel-6-3E,v23,ivytown,core -GenuineIntel-6-2D,v23,jaketown,core -GenuineIntel-6-(57|85),v10,knightslanding,core -GenuineIntel-6-A[AC],v1.04,meteorlake,core -GenuineIntel-6-1[AEF],v3,nehalemep,core -GenuineIntel-6-2E,v3,nehalemex,core +GenuineIntel-6-3E,v24,ivytown,core +GenuineIntel-6-2D,v24,jaketown,core +GenuineIntel-6-(57|85),v16,knightslanding,core +GenuineIntel-6-BD,v1.00,lunarlake,core +GenuineIntel-6-A[AC],v1.06,meteorlake,core +GenuineIntel-6-1[AEF],v4,nehalemep,core +GenuineIntel-6-2E,v4,nehalemex,core GenuineIntel-6-A7,v1.01,rocketlake,core GenuineIntel-6-2A,v19,sandybridge,core -GenuineIntel-6-(8F|CF),v1.15,sapphirerapids,core +GenuineIntel-6-8F,v1.16,sapphirerapids,core GenuineIntel-6-AF,v1.00,sierraforest,core GenuineIntel-6-(37|4A|4C|4D|5A),v15,silvermont,core GenuineIntel-6-(4E|5E|8E|9E|A5|A6),v57,skylake,core -GenuineIntel-6-55-[01234],v1.31,skylakex,core +GenuineIntel-6-55-[01234],v1.32,skylakex,core GenuineIntel-6-86,v1.21,snowridgex,core GenuineIntel-6-8[CD],v1.13,tigerlake,core -GenuineIntel-6-2C,v4,westmereep-dp,core -GenuineIntel-6-25,v3,westmereep-sp,core -GenuineIntel-6-2F,v3,westmereex,core +GenuineIntel-6-2C,v5,westmereep-dp,core +GenuineIntel-6-25,v4,westmereep-sp,core +GenuineIntel-6-2F,v4,westmereex,core AuthenticAMD-23-([12][0-9A-F]|[0-9A-F]),v2,amdzen1,core AuthenticAMD-23-[[:xdigit:]]+,v1,amdzen2,core AuthenticAMD-25-([245][[:xdigit:]]|[[:xdigit:]]),v1,amdzen3,core diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/cache.json b/tools/perf/pmu-events/arch/x86/meteorlake/cache.json index 1de0200b32f6..5fef87502d4b 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/cache.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/cache.json @@ -966,6 +966,16 @@ "UMask": "0x3", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts demand data reads that were supplied by the L3 cache where a snoop was sent, the snoop hit, and modified data was forwarded.", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10003C0001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts demand data reads that resulted in a snoop hit in another cores caches, data forwarding is required as the data is modified.", "EventCode": "0x2A,0x2B", @@ -976,6 +986,16 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts demand data reads that were supplied by the L3 cache where a snoop was sent, the snoop hit, and non-modified data was forwarded.", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_DATA_RD.L3_HIT.SNOOP_HIT_WITH_FWD", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x8003C0001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts demand data reads that resulted in a snoop hit in another cores caches which forwarded the unmodified data to the requesting core.", "EventCode": "0x2A,0x2B", @@ -986,6 +1006,16 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts demand reads for ownership (RFO) and software prefetches for exclusive ownership (PREFETCHW) that were supplied by the L3 cache where a snoop was sent, the snoop hit, and modified data was forwarded.", + "EventCode": "0xB7", + "EventName": "OCR.DEMAND_RFO.L3_HIT.SNOOP_HITM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10003C0002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that resulted in a snoop hit in another cores caches, data forwarding is required as the data is modified.", "EventCode": "0x2A,0x2B", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/frontend.json b/tools/perf/pmu-events/arch/x86/meteorlake/frontend.json index 8264419500a5..9da8689eda81 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/frontend.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/frontend.json @@ -460,6 +460,27 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "CounterMask": "6", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "CounterMask": "1", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_FE_WAS_OK", + "Invert": "1", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "SampleAfterValue": "1000003", + "UMask": "0x1", + "Unit": "cpu_core" + }, { "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled", "EventCode": "0x9c", @@ -470,22 +491,22 @@ "Unit": "cpu_core" }, { - "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled", + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", "CounterMask": "6", "EventCode": "0x9c", "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE", - "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_core" }, { - "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled", + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", "CounterMask": "1", "EventCode": "0x9c", "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK", "Invert": "1", - "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", "SampleAfterValue": "1000003", "UMask": "0x1", "Unit": "cpu_core" diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/memory.json b/tools/perf/pmu-events/arch/x86/meteorlake/memory.json index 2605e1d0ba9f..a5b83293f157 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/memory.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/memory.json @@ -66,6 +66,14 @@ "UMask": "0x84", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.", + "EventCode": "0xc3", + "EventName": "MACHINE_CLEARS.MEMORY_ORDERING", + "SampleAfterValue": "20003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of machine clears due to memory ordering conflicts.", "EventCode": "0xc3", @@ -75,6 +83,15 @@ "UMask": "0x2", "Unit": "cpu_core" }, + { + "BriefDescription": "Cycles while L1 cache miss demand load is outstanding.", + "CounterMask": "2", + "EventCode": "0x47", + "EventName": "MEMORY_ACTIVITY.CYCLES_L1D_MISS", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_core" + }, { "BriefDescription": "Execution stalls while L1 cache miss demand load is outstanding.", "CounterMask": "3", @@ -279,6 +296,26 @@ "UMask": "0x4", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts demand data reads that were not supplied by the L3 cache.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that were not supplied by the L3 cache.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.L3_MISS", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x3FBFC00002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, { "BriefDescription": "Counts demand data read requests that miss the L3 cache.", "EventCode": "0x21", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/other.json b/tools/perf/pmu-events/arch/x86/meteorlake/other.json index f4c603599df4..d55e792c0c43 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/other.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/other.json @@ -7,6 +7,46 @@ "UMask": "0x8", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts demand data reads that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts demand data reads that were supplied by DRAM.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_DATA_RD.DRAM", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x184000001", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that have any type of response.", + "EventCode": "0x2A,0x2B", + "EventName": "OCR.DEMAND_RFO.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10002", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_core" + }, + { + "BriefDescription": "Counts streaming stores that have any type of response.", + "EventCode": "0xB7", + "EventName": "OCR.STREAMING_WR.ANY_RESPONSE", + "MSRIndex": "0x1a6,0x1a7", + "MSRValue": "0x10800", + "SampleAfterValue": "100003", + "UMask": "0x1", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts streaming stores that have any type of response.", "EventCode": "0x2A,0x2B", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json b/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json index 352c5efafc06..deaa7aba93f7 100644 --- a/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/meteorlake/pipeline.json @@ -217,6 +217,15 @@ "UMask": "0x50", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of mispredicted taken JCC (Jump on Conditional Code) branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.COND_TAKEN", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0xfe", + "Unit": "cpu_atom" + }, { "BriefDescription": "number of branch instructions retired that were mispredicted and taken.", "EventCode": "0xc5", @@ -292,6 +301,15 @@ "UMask": "0xc0", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the number of mispredicted near taken branch instructions retired.", + "EventCode": "0xc5", + "EventName": "BR_MISP_RETIRED.NEAR_TAKEN", + "PEBS": "1", + "SampleAfterValue": "200003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Number of near branch instructions retired that were mispredicted and taken.", "EventCode": "0xc5", @@ -733,7 +751,7 @@ "Unit": "cpu_core" }, { - "BriefDescription": "INT_MISC.UNKNOWN_BRANCH_CYCLES", + "BriefDescription": "Bubble cycles of BAClear (Unknown Branch).", "EventCode": "0xad", "EventName": "INT_MISC.UNKNOWN_BRANCH_CYCLES", "MSRIndex": "0x3F7", @@ -1045,6 +1063,14 @@ "UMask": "0x3", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to Branch Mispredict", + "EventCode": "0x73", + "EventName": "TOPDOWN_BAD_SPECULATION.MISPREDICT", + "SampleAfterValue": "1000003", + "UMask": "0x4", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to a machine clear (nuke).", "EventCode": "0x73", @@ -1068,6 +1094,22 @@ "UMask": "0x1", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to memory reservation stall (scheduler not being able to accept another uop). This could be caused by RSV full or load/store buffer block.", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.MEM_SCHEDULER", + "SampleAfterValue": "1000003", + "UMask": "0x2", + "Unit": "cpu_atom" + }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to IEC and FPC RAT stalls - which can be due to the FIQ and IEC reservation station stall (integer, FP and SIMD scheduler not being able to accept another uop. )", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.NON_MEM_SCHEDULER", + "SampleAfterValue": "1000003", + "UMask": "0x8", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to mrbl stall. A 'marble' refers to a physical register file entry, also known as the physical destination (PDST).", "EventCode": "0x74", @@ -1076,6 +1118,14 @@ "UMask": "0x20", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to ROB full", + "EventCode": "0x74", + "EventName": "TOPDOWN_BE_BOUND.REORDER_BUFFER", + "SampleAfterValue": "1000003", + "UMask": "0x40", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots every cycle that were not consumed by the backend due to iq/jeu scoreboards or ms scb", "EventCode": "0x74", @@ -1156,6 +1206,14 @@ "UMask": "0x10", "Unit": "cpu_atom" }, + { + "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend that do not categorize into any other common frontend stall", + "EventCode": "0x71", + "EventName": "TOPDOWN_FE_BOUND.OTHER", + "SampleAfterValue": "1000003", + "UMask": "0x80", + "Unit": "cpu_atom" + }, { "BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to predecode wrong", "EventCode": "0x71", @@ -1398,6 +1456,14 @@ "UMask": "0x1", "Unit": "cpu_core" }, + { + "BriefDescription": "Counts the total number of uops retired.", + "EventCode": "0xc2", + "EventName": "UOPS_RETIRED.ALL", + "PEBS": "1", + "SampleAfterValue": "2000003", + "Unit": "cpu_atom" + }, { "BriefDescription": "Cycles with retired uop(s).", "CounterMask": "1", diff --git a/tools/perf/pmu-events/arch/x86/meteorlake/uncore-other.json b/tools/perf/pmu-events/arch/x86/meteorlake/uncore-other.json new file mode 100644 index 000000000000..2af92e43b28a --- /dev/null +++ b/tools/perf/pmu-events/arch/x86/meteorlake/uncore-other.json @@ -0,0 +1,9 @@ +[ + { + "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.", + "EventCode": "0xff", + "EventName": "UNC_CLOCK.SOCKET", + "PerPkg": "1", + "Unit": "CLOCK" + } +] diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/cache.json b/tools/perf/pmu-events/arch/x86/nehalemep/cache.json index 1a132fcda964..5113a4e059e4 100644 --- a/tools/perf/pmu-events/arch/x86/nehalemep/cache.json +++ b/tools/perf/pmu-events/arch/x86/nehalemep/cache.json @@ -287,7 +287,7 @@ "UMask": "0x20" }, { - "BriefDescription": "L2 lines alloacated", + "BriefDescription": "L2 lines allocated", "EventCode": "0xF1", "EventName": "L2_LINES_IN.ANY", "SampleAfterValue": "100000", diff --git a/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json b/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json index c03f8990fa82..196ae1d9b157 100644 --- a/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/nehalemep/floating-point.json @@ -8,7 +8,7 @@ "UMask": "0x1" }, { - "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)", + "BriefDescription": "X87 Floating point assists for invalid input value (Precise Event)", "EventCode": "0xF7", "EventName": "FP_ASSIST.INPUT", "PEBS": "1", diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/cache.json b/tools/perf/pmu-events/arch/x86/nehalemex/cache.json index a4142cd2ca86..0042e53fdc78 100644 --- a/tools/perf/pmu-events/arch/x86/nehalemex/cache.json +++ b/tools/perf/pmu-events/arch/x86/nehalemex/cache.json @@ -287,7 +287,7 @@ "UMask": "0x20" }, { - "BriefDescription": "L2 lines alloacated", + "BriefDescription": "L2 lines allocated", "EventCode": "0xF1", "EventName": "L2_LINES_IN.ANY", "SampleAfterValue": "100000", diff --git a/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json b/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json index c03f8990fa82..196ae1d9b157 100644 --- a/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/nehalemex/floating-point.json @@ -8,7 +8,7 @@ "UMask": "0x1" }, { - "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)", + "BriefDescription": "X87 Floating point assists for invalid input value (Precise Event)", "EventCode": "0xF7", "EventName": "FP_ASSIST.INPUT", "PEBS": "1", diff --git a/tools/perf/pmu-events/arch/x86/rocketlake/rkl-metrics.json b/tools/perf/pmu-events/arch/x86/rocketlake/rkl-metrics.json index a0191c8b708d..0c880e415669 100644 --- a/tools/perf/pmu-events/arch/x86/rocketlake/rkl-metrics.json +++ b/tools/perf/pmu-events/arch/x86/rocketlake/rkl-metrics.json @@ -1551,7 +1551,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/sapphirerapids/frontend.json b/tools/perf/pmu-events/arch/x86/sapphirerapids/frontend.json index 860a415e5e79..9e53da55d0c1 100644 --- a/tools/perf/pmu-events/arch/x86/sapphirerapids/frontend.json +++ b/tools/perf/pmu-events/arch/x86/sapphirerapids/frontend.json @@ -333,29 +333,56 @@ "UMask": "0x20" }, { - "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled", + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CORE]", "EventCode": "0x9c", - "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE", - "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "EventName": "IDQ_BUBBLES.CORE", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CORE]", "SampleAfterValue": "1000003", "UMask": "0x1" }, { - "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled", + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "CounterMask": "6", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "CounterMask": "1", + "EventCode": "0x9c", + "EventName": "IDQ_BUBBLES.CYCLES_FE_WAS_OK", + "Invert": "1", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Uops not delivered by IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CORE]", + "EventCode": "0x9c", + "EventName": "IDQ_UOPS_NOT_DELIVERED.CORE", + "PublicDescription": "Counts the number of uops not delivered to by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CORE]", + "SampleAfterValue": "1000003", + "UMask": "0x1" + }, + { + "BriefDescription": "Cycles when no uops are not delivered by the IDQ when backend of the machine is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", "CounterMask": "6", "EventCode": "0x9c", "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_0_UOPS_DELIV.CORE", - "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "PublicDescription": "Counts the number of cycles when no uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_0_UOPS_DELIV.CORE]", "SampleAfterValue": "1000003", "UMask": "0x1" }, { - "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled", + "BriefDescription": "Cycles when optimal number of uops was delivered to the back-end when the back-end is not stalled [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", "CounterMask": "1", "EventCode": "0x9c", "EventName": "IDQ_UOPS_NOT_DELIVERED.CYCLES_FE_WAS_OK", "Invert": "1", - "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle.", + "PublicDescription": "Counts the number of cycles when the optimal number of uops were delivered by the Instruction Decode Queue (IDQ) to the back-end of the pipeline when there was no back-end stalls. This event counts for one SMT thread in a given cycle. [This event is alias to IDQ_BUBBLES.CYCLES_FE_WAS_OK]", "SampleAfterValue": "1000003", "UMask": "0x1" } diff --git a/tools/perf/pmu-events/arch/x86/sapphirerapids/spr-metrics.json b/tools/perf/pmu-events/arch/x86/sapphirerapids/spr-metrics.json index 222212abd811..06c6d67cb76b 100644 --- a/tools/perf/pmu-events/arch/x86/sapphirerapids/spr-metrics.json +++ b/tools/perf/pmu-events/arch/x86/sapphirerapids/spr-metrics.json @@ -1944,13 +1944,6 @@ "MetricName": "tsx_aborted_cycles", "ScaleUnit": "100%" }, - { - "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", - "MetricGroup": "transaction", - "MetricName": "tsx_cycles_per_elision", - "ScaleUnit": "1cycles / elision" - }, { "BriefDescription": "Number of cycles within a transaction divided by the number of transactions.", "MetricExpr": "(cycles\\-t / tx\\-start if has_event(cycles\\-t) else 0)", diff --git a/tools/perf/pmu-events/arch/x86/sapphirerapids/uncore-cache.json b/tools/perf/pmu-events/arch/x86/sapphirerapids/uncore-cache.json index 3fa660694bc7..cf6fa70f37c1 100644 --- a/tools/perf/pmu-events/arch/x86/sapphirerapids/uncore-cache.json +++ b/tools/perf/pmu-events/arch/x86/sapphirerapids/uncore-cache.json @@ -4591,7 +4591,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_HIT_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -4825,7 +4825,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -4870,7 +4870,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -4924,7 +4924,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -4942,7 +4942,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_PREF_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT_PREF_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -4977,7 +4977,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_PREF_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -5128,7 +5128,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFDATA_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -5154,7 +5154,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_LLCPREFRFO_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -5260,7 +5260,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", @@ -5295,7 +5295,7 @@ }, { "BriefDescription": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_CXL_ACC_LOCAL", - "EventCode": "0x35", + "EventCode": "0x36", "EventName": "UNC_CHA_TOR_OCCUPANCY.IA_MISS_RFO_PREF_CXL_ACC_LOCAL", "PerPkg": "1", "PortMask": "0x000", diff --git a/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json b/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json index 2795a404bb58..faa615c57893 100644 --- a/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json +++ b/tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json @@ -1473,7 +1473,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json index fa4209809c57..4a8f8eeb7525 100644 --- a/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json +++ b/tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json @@ -1781,7 +1781,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json b/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json index fab084e1bc69..f11860f39c18 100644 --- a/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json +++ b/tools/perf/pmu-events/arch/x86/tigerlake/tgl-metrics.json @@ -62,6 +62,12 @@ "MetricName": "C9_Pkg_Residency", "ScaleUnit": "100%" }, + { + "BriefDescription": "Uncore frequency per die [GHZ]", + "MetricExpr": "tma_info_system_socket_clks / #num_dies / duration_time / 1e9", + "MetricGroup": "SoC", + "MetricName": "UNCORE_FREQ" + }, { "BriefDescription": "Percentage of cycles spent in System Management Interrupts.", "MetricExpr": "((msr@aperf@ - cycles) / msr@aperf@ if msr@smi@ > 0 else 0)", @@ -1026,6 +1032,12 @@ "MetricGroup": "SMT", "MetricName": "tma_info_system_smt_2t_utilization" }, + { + "BriefDescription": "Socket actual clocks when any core is active on that socket", + "MetricExpr": "UNC_CLOCK.SOCKET", + "MetricGroup": "SoC", + "MetricName": "tma_info_system_socket_clks" + }, { "BriefDescription": "Average Frequency Utilization relative nominal frequency", "MetricExpr": "tma_info_thread_clks / CPU_CLK_UNHALTED.REF_TSC", @@ -1539,7 +1551,7 @@ }, { "BriefDescription": "Number of cycles within a transaction divided by the number of elisions.", - "MetricExpr": "(cycles\\-t / el\\-start if has_event(cycles\\-t) else 0)", + "MetricExpr": "(cycles\\-t / el\\-start if has_event(el\\-start) else 0)", "MetricGroup": "transaction", "MetricName": "tsx_cycles_per_elision", "ScaleUnit": "1cycles / elision" diff --git a/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json b/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json index c03f8990fa82..196ae1d9b157 100644 --- a/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/westmereep-dp/floating-point.json @@ -8,7 +8,7 @@ "UMask": "0x1" }, { - "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)", + "BriefDescription": "X87 Floating point assists for invalid input value (Precise Event)", "EventCode": "0xF7", "EventName": "FP_ASSIST.INPUT", "PEBS": "1", diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json index e00c301640f3..d025e2c0cf1c 100644 --- a/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json +++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/cache.json @@ -182,7 +182,7 @@ "UMask": "0x20" }, { - "BriefDescription": "L2 lines alloacated", + "BriefDescription": "L2 lines allocated", "EventCode": "0xF1", "EventName": "L2_LINES_IN.ANY", "SampleAfterValue": "100000", diff --git a/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json b/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json index c03f8990fa82..196ae1d9b157 100644 --- a/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/westmereep-sp/floating-point.json @@ -8,7 +8,7 @@ "UMask": "0x1" }, { - "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)", + "BriefDescription": "X87 Floating point assists for invalid input value (Precise Event)", "EventCode": "0xF7", "EventName": "FP_ASSIST.INPUT", "PEBS": "1", diff --git a/tools/perf/pmu-events/arch/x86/westmereex/cache.json b/tools/perf/pmu-events/arch/x86/westmereex/cache.json index 6c7c52733dda..18d61d43e4c9 100644 --- a/tools/perf/pmu-events/arch/x86/westmereex/cache.json +++ b/tools/perf/pmu-events/arch/x86/westmereex/cache.json @@ -182,7 +182,7 @@ "UMask": "0x20" }, { - "BriefDescription": "L2 lines alloacated", + "BriefDescription": "L2 lines allocated", "EventCode": "0xF1", "EventName": "L2_LINES_IN.ANY", "SampleAfterValue": "100000", diff --git a/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json b/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json index c03f8990fa82..196ae1d9b157 100644 --- a/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json +++ b/tools/perf/pmu-events/arch/x86/westmereex/floating-point.json @@ -8,7 +8,7 @@ "UMask": "0x1" }, { - "BriefDescription": "X87 Floating poiint assists for invalid input value (Precise Event)", + "BriefDescription": "X87 Floating point assists for invalid input value (Precise Event)", "EventCode": "0xF7", "EventName": "FP_ASSIST.INPUT", "PEBS": "1", diff --git a/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json b/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json index 1c61d18a4b5f..026236558d05 100644 --- a/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json +++ b/tools/perf/pmu-events/arch/x86/westmereex/pipeline.json @@ -45,7 +45,7 @@ "UMask": "0x1" }, { - "BriefDescription": "Early Branch Prediciton Unit clears", + "BriefDescription": "Early Branch Prediction Unit clears", "EventCode": "0xE8", "EventName": "BPU_CLEARS.EARLY", "SampleAfterValue": "2000000", diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 12bd043a05e3..13727421d424 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -244,6 +244,14 @@ static const struct pmu_event pmu_events__test_soc_sys[] = { .topic = "uncore", .pmu = "uncore_sys_ccn_pmu", }, + { + .name = "sys_cmn_pmu.hnf_cache_miss", + .event = "eventid=0x1,type=0x5", + .desc = "Counts total cache misses in first lookup result (high priority). Unit: uncore_sys_cmn_pmu ", + .compat = "(434|436|43c|43a).*", + .topic = "uncore", + .pmu = "uncore_sys_cmn_pmu", + }, { .name = 0, .event = 0, diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 72ba4a9239c6..3c091ab75305 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -289,6 +289,7 @@ class JsonEvent: 'cpu_core': 'cpu_core', 'cpu_atom': 'cpu_atom', 'ali_drw': 'ali_drw', + 'arm_cmn': 'arm_cmn', } return table[unit] if unit in table else f'uncore_{unit.lower()}' @@ -298,6 +299,7 @@ class JsonEvent: if 'ExtSel' in jd: eventcode |= int(jd['ExtSel']) << 8 configcode = int(jd['ConfigCode'], 0) if 'ConfigCode' in jd else None + eventidcode = int(jd['EventidCode'], 0) if 'EventidCode' in jd else None self.name = jd['EventName'].lower() if 'EventName' in jd else None self.topic = '' self.compat = jd.get('Compat') @@ -335,7 +337,13 @@ class JsonEvent: if precise and self.desc and '(Precise Event)' not in self.desc: extra_desc += ' (Must be precise)' if precise == '2' else (' (Precise ' 'event)') - event = f'config={llx(configcode)}' if configcode is not None else f'event={llx(eventcode)}' + event = None + if configcode is not None: + event = f'config={llx(configcode)}' + elif eventidcode is not None: + event = f'eventid={llx(eventidcode)}' + else: + event = f'event={llx(eventcode)}' event_fields = [ ('AnyThread', 'any='), ('PortMask', 'ch_mask='), @@ -345,6 +353,7 @@ class JsonEvent: ('Invert', 'inv='), ('SampleAfterValue', 'period='), ('UMask', 'umask='), + ('NodeType', 'type='), ] for key, value in event_fields: if key in jd and jd[key] != '0': @@ -764,8 +773,8 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { continue _args.output_file.write(f"""\t{{ \t\t.metric_table = {{ -\t\t\t.entries = {tblname}, -\t\t\t.length = ARRAY_SIZE({tblname}) +\t\t\t.pmus = {tblname}, +\t\t\t.num_pmus = ARRAY_SIZE({tblname}) \t\t}}, \t\t.name = \"{tblname}\", \t}}, @@ -967,68 +976,99 @@ int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, return 0; } -const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) +static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) { - const struct pmu_events_table *table = NULL; - char *cpuid = perf_pmu__getcpuid(pmu); + static struct { + const struct pmu_events_map *map; + struct perf_pmu *pmu; + } last_result; + static struct { + const struct pmu_events_map *map; + char *cpuid; + } last_map_search; + static bool has_last_result, has_last_map_search; + const struct pmu_events_map *map = NULL; + char *cpuid = NULL; size_t i; - /* on some platforms which uses cpus map, cpuid can be NULL for + if (has_last_result && last_result.pmu == pmu) + return last_result.map; + + cpuid = perf_pmu__getcpuid(pmu); + + /* + * On some platforms which uses cpus map, cpuid can be NULL for * PMUs other than CORE PMUs. */ if (!cpuid) + goto out_update_last_result; + + if (has_last_map_search && !strcmp(last_map_search.cpuid, cpuid)) { + map = last_map_search.map; + free(cpuid); + } else { + i = 0; + for (;;) { + map = &pmu_events_map[i++]; + + if (!map->arch) { + map = NULL; + break; + } + + if (!strcmp_cpuid_str(map->cpuid, cpuid)) + break; + } + free(last_map_search.cpuid); + last_map_search.cpuid = cpuid; + last_map_search.map = map; + has_last_map_search = true; + } +out_update_last_result: + last_result.pmu = pmu; + last_result.map = map; + has_last_result = true; + return map; +} + +const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) +{ + const struct pmu_events_map *map = map_for_pmu(pmu); + + if (!map) return NULL; - i = 0; - for (;;) { - const struct pmu_events_map *map = &pmu_events_map[i++]; - if (!map->arch) - break; + if (!pmu) + return &map->event_table; - if (!strcmp_cpuid_str(map->cpuid, cpuid)) { - table = &map->event_table; - break; - } - } - free(cpuid); - if (!pmu || !table) - return table; - - for (i = 0; i < table->num_pmus; i++) { - const struct pmu_table_entry *table_pmu = &table->pmus[i]; + for (size_t i = 0; i < map->event_table.num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &map->event_table.pmus[i]; const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; if (pmu__name_match(pmu, pmu_name)) - return table; + return &map->event_table; } return NULL; } const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu) { - const struct pmu_metrics_table *table = NULL; - char *cpuid = perf_pmu__getcpuid(pmu); - int i; + const struct pmu_events_map *map = map_for_pmu(pmu); - /* on some platforms which uses cpus map, cpuid can be NULL for - * PMUs other than CORE PMUs. - */ - if (!cpuid) + if (!map) return NULL; - i = 0; - for (;;) { - const struct pmu_events_map *map = &pmu_events_map[i++]; - if (!map->arch) - break; + if (!pmu) + return &map->metric_table; - if (!strcmp_cpuid_str(map->cpuid, cpuid)) { - table = &map->metric_table; - break; - } + for (size_t i = 0; i < map->metric_table.num_pmus; i++) { + const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; + const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; + + if (pmu__name_match(pmu, pmu_name)) + return &map->metric_table; } - free(cpuid); - return table; + return NULL; } const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) diff --git a/tools/perf/pmu-events/metric.py b/tools/perf/pmu-events/metric.py index 3e673f25d5fd..92acd89ed97a 100644 --- a/tools/perf/pmu-events/metric.py +++ b/tools/perf/pmu-events/metric.py @@ -558,8 +558,7 @@ def ParsePerfJson(orig: str) -> Expression: # Convert accidentally converted scientific notation constants back py = re.sub(r'([0-9]+)Event\(r"(e[0-9]+)"\)', r'\1\2', py) # Convert all the known keywords back from events to just the keyword - keywords = ['if', 'else', 'min', 'max', 'd_ratio', 'source_count', 'has_event', 'strcmp_cpuid_str', - 'cpuid_not_more_than'] + keywords = ['if', 'else', 'min', 'max', 'd_ratio', 'source_count', 'has_event', 'strcmp_cpuid_str'] for kw in keywords: py = re.sub(rf'Event\(r"{kw}"\)', kw, py) try: diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 63d5e6d5f165..2b45ffa462a6 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -66,6 +66,7 @@ perf-y += dlfilter-test.o perf-y += sigtrap.o perf-y += event_groups.o perf-y += symbols.o +perf-y += util.o ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc)) perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o diff --git a/tools/perf/tests/attr/system-wide-dummy b/tools/perf/tests/attr/system-wide-dummy index 2f3e3eb728eb..a1e1d6a263bf 100644 --- a/tools/perf/tests/attr/system-wide-dummy +++ b/tools/perf/tests/attr/system-wide-dummy @@ -9,8 +9,10 @@ flags=8 type=1 size=136 config=9 -sample_period=4000 -sample_type=455 +sample_period=1 +# PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | +# PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER +sample_type=65671 read_format=4|20 # Event will be enabled right away. disabled=0 @@ -18,12 +20,12 @@ inherit=1 pinned=0 exclusive=0 exclude_user=0 -exclude_kernel=0 -exclude_hv=0 +exclude_kernel=1 +exclude_hv=1 exclude_idle=0 mmap=1 comm=1 -freq=1 +freq=0 inherit_stat=0 enable_on_exec=0 task=1 @@ -32,7 +34,7 @@ precise_ip=0 mmap_data=0 sample_id_all=1 exclude_host=0 -exclude_guest=0 +exclude_guest=1 exclude_callchain_kernel=0 exclude_callchain_user=0 mmap2=1 diff --git a/tools/perf/tests/attr/test-record-C0 b/tools/perf/tests/attr/test-record-C0 index 317730b906dd..198e8429a1bf 100644 --- a/tools/perf/tests/attr/test-record-C0 +++ b/tools/perf/tests/attr/test-record-C0 @@ -10,9 +10,9 @@ cpu=0 enable_on_exec=0 # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | -# PERF_SAMPLE_ID | PERF_SAMPLE_PERIOD +# PERF_SAMPLE_PERIOD | PERF_SAMPLE_IDENTIFIER # + PERF_SAMPLE_CPU added by -C 0 -sample_type=455 +sample_type=65927 # Dummy event handles mmaps, comm and task. mmap=0 diff --git a/tools/perf/tests/attr/test-record-dummy-C0 b/tools/perf/tests/attr/test-record-dummy-C0 new file mode 100644 index 000000000000..576ec48b3aaf --- /dev/null +++ b/tools/perf/tests/attr/test-record-dummy-C0 @@ -0,0 +1,55 @@ +[config] +command = record +args = --no-bpf-event -e dummy -C 0 kill >/dev/null 2>&1 +ret = 1 + +[event] +fd=1 +group_fd=-1 +cpu=0 +pid=-1 +flags=8 +type=1 +size=136 +config=9 +sample_period=4000 +# PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | +# PERF_SAMPLE_PERIOD +# + PERF_SAMPLE_CPU added by -C 0 +sample_type=391 +read_format=4|20 +disabled=0 +inherit=1 +pinned=0 +exclusive=0 +exclude_user=0 +exclude_kernel=0 +exclude_hv=0 +exclude_idle=0 +mmap=1 +comm=1 +freq=1 +inherit_stat=0 +enable_on_exec=0 +task=1 +watermark=0 +precise_ip=0 +mmap_data=0 +sample_id_all=1 +exclude_host=0 +exclude_guest=1 +exclude_callchain_kernel=0 +exclude_callchain_user=0 +mmap2=1 +comm_exec=1 +context_switch=0 +write_backward=0 +namespaces=0 +use_clockid=0 +wakeup_events=0 +bp_type=0 +config1=0 +config2=0 +branch_sample_type=0 +sample_regs_user=0 +sample_stack_user=0 diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 0ad18cf6dd22..cb6f1dd00dc4 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -123,6 +123,7 @@ static struct test_suite *generic_tests[] = { &suite__sigtrap, &suite__event_groups, &suite__symbols, + &suite__util, NULL, }; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index ed3815163d1b..3af81012014e 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -269,6 +269,16 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, if (addr + len > map__end(al.map)) len = map__end(al.map) - addr; + /* + * Some architectures (ex: powerpc) have stubs (trampolines) in kernel + * modules to manage long jumps. Check if the ip offset falls in stubs + * sections for kernel modules. And skip module address after text end + */ + if (dso->is_kmod && al.addr > dso->text_end) { + pr_debug("skipping the module address %#"PRIx64" after text end\n", al.addr); + goto out; + } + /* Read the object code using perf */ ret_len = dso__data_read_offset(dso, maps__machine(thread__maps(thread)), al.addr, buf1, len); diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 81229fa4f1e9..e3aa9d4fcf3a 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -9,6 +9,7 @@ #include #include #include +#include #include static int test_ids_union(void) @@ -74,10 +75,13 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u int ret; struct expr_parse_ctx *ctx; bool is_intel = false; - char buf[128]; + char strcmp_cpuid_buf[256]; + struct perf_pmu *pmu = perf_pmus__find_core_pmu(); + char *cpuid = perf_pmu__getcpuid(pmu); + char *escaped_cpuid1, *escaped_cpuid2; - if (!get_cpuid(buf, sizeof(buf))) - is_intel = strstr(buf, "Intel") != NULL; + TEST_ASSERT_VAL("get_cpuid", cpuid); + is_intel = strstr(cpuid, "Intel") != NULL; TEST_ASSERT_EQUAL("ids_union", test_ids_union(), 0); @@ -257,13 +261,32 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u TEST_ASSERT_VAL("source count", hashmap__size(ctx->ids) == 1); TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids, "EVENT1", &val_ptr)); + + /* Test no cpuid match */ + ret = test(ctx, "strcmp_cpuid_str(0x0)", 0); + + /* + * Test cpuid match with current cpuid. Special chars have to be + * escaped. + */ + escaped_cpuid1 = strreplace_chars('-', cpuid, "\\-"); + free(cpuid); + escaped_cpuid2 = strreplace_chars(',', escaped_cpuid1, "\\,"); + free(escaped_cpuid1); + escaped_cpuid1 = strreplace_chars('=', escaped_cpuid2, "\\="); + free(escaped_cpuid2); + scnprintf(strcmp_cpuid_buf, sizeof(strcmp_cpuid_buf), + "strcmp_cpuid_str(%s)", escaped_cpuid1); + free(escaped_cpuid1); + ret |= test(ctx, strcmp_cpuid_buf, 1); + /* has_event returns 1 when an event exists. */ expr__add_id_val(ctx, strdup("cycles"), 2); - ret = test(ctx, "has_event(cycles)", 1); + ret |= test(ctx, "has_event(cycles)", 1); expr__ctx_free(ctx); - return 0; + return ret; } DEFINE_SUITE("Simple expression parser", expr); diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 2d19657ab5e0..5b6f1e883466 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c @@ -148,8 +148,8 @@ static int find_sample(struct sample *samples, size_t nr_samples, struct thread *t, struct map *m, struct symbol *s) { while (nr_samples--) { - if (RC_CHK_ACCESS(samples->thread) == RC_CHK_ACCESS(t) && - RC_CHK_ACCESS(samples->map) == RC_CHK_ACCESS(m) && + if (RC_CHK_EQUAL(samples->thread, t) && + RC_CHK_EQUAL(samples->map, m) && samples->sym == s) return 1; samples++; diff --git a/tools/perf/tests/make b/tools/perf/tests/make index ea4c341f5af1..d9945ed25bc5 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -70,8 +70,8 @@ make_python_perf_so := $(python_perf_so) make_debug := DEBUG=1 make_nondistro := BUILD_NONDISTRO=1 make_extra_tests := EXTRA_TESTS=1 -make_bpf_skel := BUILD_BPF_SKEL=1 -make_gen_vmlinux_h := BUILD_BPF_SKEL=1 GEN_VMLINUX_H=1 +make_no_bpf_skel := BUILD_BPF_SKEL=0 +make_gen_vmlinux_h := GEN_VMLINUX_H=1 make_no_libperl := NO_LIBPERL=1 make_no_libpython := NO_LIBPYTHON=1 make_no_scripts := NO_LIBPYTHON=1 NO_LIBPERL=1 @@ -138,7 +138,8 @@ endif run += make_python_perf_so run += make_debug run += make_nondistro -run += make_build_bpf_skel +run += make_extra_tests +run += make_no_bpf_skel run += make_gen_vmlinux_h run += make_no_libperl run += make_no_libpython diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index d47f1f871164..f78be21a5999 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -771,12 +771,12 @@ static int test__checkevent_pmu_events_mix(struct evlist *evlist) return TEST_OK; } -static int test__checkterms_simple(struct list_head *terms) +static int test__checkterms_simple(struct parse_events_terms *terms) { struct parse_events_term *term; /* config=10 */ - term = list_entry(terms->next, struct parse_events_term, list); + term = list_entry(terms->terms.next, struct parse_events_term, list); TEST_ASSERT_VAL("wrong type term", term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG); TEST_ASSERT_VAL("wrong type val", @@ -2363,7 +2363,7 @@ static const struct evlist_test test__events_pmu[] = { struct terms_test { const char *str; - int (*check)(struct list_head *terms); + int (*check)(struct parse_events_terms *terms); }; static const struct terms_test test__terms[] = { @@ -2467,11 +2467,11 @@ static int test__events2(struct test_suite *test __maybe_unused, int subtest __m static int test_term(const struct terms_test *t) { - struct list_head terms; + struct parse_events_terms terms; int ret; - INIT_LIST_HEAD(&terms); + parse_events_terms__init(&terms); ret = parse_events_terms(&terms, t->str, /*input=*/ NULL); if (ret) { pr_debug("failed to parse terms '%s', err %d\n", @@ -2480,7 +2480,7 @@ static int test_term(const struct terms_test *t) } ret = t->check(&terms); - parse_events_terms__purge(&terms); + parse_events_terms__exit(&terms); return ret; } @@ -2514,9 +2514,14 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest while ((pmu = perf_pmus__scan(pmu)) != NULL) { struct stat st; char path[PATH_MAX]; + char pmu_event[PATH_MAX]; + char *buf = NULL; + FILE *file; struct dirent *ent; + size_t len = 0; DIR *dir; int err; + int n; snprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/events/", sysfs__mountpoint(), pmu->name); @@ -2538,11 +2543,45 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest struct evlist_test e = { .name = NULL, }; char name[2 * NAME_MAX + 1 + 12 + 3]; int test_ret; + bool is_event_parameterized = 0; /* Names containing . are special and cannot be used directly */ if (strchr(ent->d_name, '.')) continue; + /* exclude parametrized ones (name contains '?') */ + n = snprintf(pmu_event, sizeof(pmu_event), "%s%s", path, ent->d_name); + if (n >= PATH_MAX) { + pr_err("pmu event name crossed PATH_MAX(%d) size\n", PATH_MAX); + continue; + } + + file = fopen(pmu_event, "r"); + if (!file) { + pr_debug("can't open pmu event file for '%s'\n", ent->d_name); + ret = combine_test_results(ret, TEST_FAIL); + continue; + } + + if (getline(&buf, &len, file) < 0) { + pr_debug(" pmu event: %s is a null event\n", ent->d_name); + ret = combine_test_results(ret, TEST_FAIL); + fclose(file); + continue; + } + + if (strchr(buf, '?')) + is_event_parameterized = 1; + + free(buf); + buf = NULL; + fclose(file); + + if (is_event_parameterized == 1) { + pr_debug("skipping parametrized PMU event: %s which contains ?\n", pmu_event); + continue; + } + snprintf(name, sizeof(name), "%s/event=%s/u", pmu->name, ent->d_name); e.name = name; diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index f5321fbdee79..a56d32905743 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -245,7 +245,7 @@ static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = { }, .alias_str = "event=0x2b", .alias_long_desc = "ddr write-cycles event", - .matching_pmu = "uncore_sys_ddr_pmu", + .matching_pmu = "uncore_sys_ddr_pmu0", }; static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = { @@ -259,12 +259,27 @@ static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = { }, .alias_str = "config=0x2c", .alias_long_desc = "ccn read-cycles event", - .matching_pmu = "uncore_sys_ccn_pmu", + .matching_pmu = "uncore_sys_ccn_pmu4", +}; + +static const struct perf_pmu_test_event sys_cmn_pmu_hnf_cache_miss = { + .event = { + .name = "sys_cmn_pmu.hnf_cache_miss", + .event = "eventid=0x1,type=0x5", + .desc = "Counts total cache misses in first lookup result (high priority)", + .topic = "uncore", + .pmu = "uncore_sys_cmn_pmu", + .compat = "(434|436|43c|43a).*", + }, + .alias_str = "eventid=0x1,type=0x5", + .alias_long_desc = "Counts total cache misses in first lookup result (high priority)", + .matching_pmu = "uncore_sys_cmn_pmu0", }; static const struct perf_pmu_test_event *sys_events[] = { &sys_ddr_pmu_write_cycles, &sys_ccn_pmu_read_cycles, + &sys_cmn_pmu_hnf_cache_miss, NULL }; @@ -615,6 +630,12 @@ static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu) .count = &matched_count, }; + if (strcmp(pmu_name, test_event.matching_pmu)) { + pr_debug("testing aliases uncore PMU %s: mismatched matching_pmu, %s vs %s\n", + pmu_name, test_event.matching_pmu, pmu_name); + return -1; + } + err = perf_pmu__find_event(pmu, event->name, &args, test_core_pmu_event_aliases_cb); if (err) { @@ -701,6 +722,46 @@ static struct perf_pmu_test_pmu test_pmus[] = { &sys_ccn_pmu_read_cycles, }, }, + { + .pmu = { + .name = (char *)"uncore_sys_cmn_pmu0", + .is_uncore = 1, + .id = (char *)"43401", + }, + .aliases = { + &sys_cmn_pmu_hnf_cache_miss, + }, + }, + { + .pmu = { + .name = (char *)"uncore_sys_cmn_pmu0", + .is_uncore = 1, + .id = (char *)"43602", + }, + .aliases = { + &sys_cmn_pmu_hnf_cache_miss, + }, + }, + { + .pmu = { + .name = (char *)"uncore_sys_cmn_pmu0", + .is_uncore = 1, + .id = (char *)"43c03", + }, + .aliases = { + &sys_cmn_pmu_hnf_cache_miss, + }, + }, + { + .pmu = { + .name = (char *)"uncore_sys_cmn_pmu0", + .is_uncore = 1, + .id = (char *)"43a01", + }, + .aliases = { + &sys_cmn_pmu_hnf_cache_miss, + }, + } }; /* Test that aliases generated are as expected */ diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c index eb60e5f66859..8f18127d876a 100644 --- a/tools/perf/tests/pmu.c +++ b/tools/perf/tests/pmu.c @@ -128,30 +128,35 @@ static int test_format_dir_put(char *dir) return system(buf); } -static struct list_head *test_terms_list(void) +static void add_test_terms(struct parse_events_terms *terms) { - static LIST_HEAD(terms); unsigned int i; - for (i = 0; i < ARRAY_SIZE(test_terms); i++) - list_add_tail(&test_terms[i].list, &terms); + for (i = 0; i < ARRAY_SIZE(test_terms); i++) { + struct parse_events_term *clone; - return &terms; + parse_events_term__clone(&clone, &test_terms[i]); + list_add_tail(&clone->list, &terms->terms); + } } static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { char dir[PATH_MAX]; char *format; - struct list_head *terms = test_terms_list(); + struct parse_events_terms terms; struct perf_event_attr attr; struct perf_pmu *pmu; int fd; int ret; + parse_events_terms__init(&terms); + add_test_terms(&terms); pmu = zalloc(sizeof(*pmu)); - if (!pmu) + if (!pmu) { + parse_events_terms__exit(&terms); return -ENOMEM; + } INIT_LIST_HEAD(&pmu->format); INIT_LIST_HEAD(&pmu->aliases); @@ -159,6 +164,7 @@ static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe format = test_format_dir_get(dir, sizeof(dir)); if (!format) { free(pmu); + parse_events_terms__exit(&terms); return -EINVAL; } @@ -175,7 +181,7 @@ static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe if (ret) goto out; - ret = perf_pmu__config_terms(pmu, &attr, terms, /*zero=*/false, /*err=*/NULL); + ret = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/false, /*err=*/NULL); if (ret) goto out; @@ -191,6 +197,7 @@ static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe out: test_format_dir_put(format); perf_pmu__delete(pmu); + parse_events_terms__exit(&terms); return ret; } diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop.sh b/tools/perf/tests/shell/coresight/asm_pure_loop.sh index 779bc8608e1e..2d65defb7e0f 100755 --- a/tools/perf/tests/shell/coresight/asm_pure_loop.sh +++ b/tools/perf/tests/shell/coresight/asm_pure_loop.sh @@ -5,9 +5,13 @@ # Carsten Haitzler , 2021 TEST="asm_pure_loop" + +# shellcheck source=../lib/coresight.sh . "$(dirname $0)"/../lib/coresight.sh + ARGS="" DATV="out" +# shellcheck disable=SC2153 DATA="$DATD/perf-$TEST-$DATV.data" perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS diff --git a/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh b/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh index 08a44e52ce9b..ddcc9bb850f5 100755 --- a/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh +++ b/tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh @@ -5,9 +5,13 @@ # Carsten Haitzler , 2021 TEST="memcpy_thread" + +# shellcheck source=../lib/coresight.sh . "$(dirname $0)"/../lib/coresight.sh + ARGS="16 10 1" DATV="16k_10" +# shellcheck disable=SC2153 DATA="$DATD/perf-$TEST-$DATV.data" perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS diff --git a/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh b/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh index c83a200dede4..2ce5e139b2fd 100755 --- a/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh +++ b/tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh @@ -5,9 +5,13 @@ # Carsten Haitzler , 2021 TEST="thread_loop" + +# shellcheck source=../lib/coresight.sh . "$(dirname $0)"/../lib/coresight.sh + ARGS="10 1" DATV="check-tid-10th" +# shellcheck disable=SC2153 DATA="$DATD/perf-$TEST-$DATV.data" STDO="$DATD/perf-$TEST-$DATV.stdout" diff --git a/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh b/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh index 6346fd5e87c8..3ad9498753d7 100755 --- a/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh +++ b/tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh @@ -5,9 +5,13 @@ # Carsten Haitzler , 2021 TEST="thread_loop" + +# shellcheck source=../lib/coresight.sh . "$(dirname $0)"/../lib/coresight.sh + ARGS="2 20" DATV="check-tid-2th" +# shellcheck disable=SC2153 DATA="$DATD/perf-$TEST-$DATV.data" STDO="$DATD/perf-$TEST-$DATV.stdout" diff --git a/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh b/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh index 7304e3d3a6ff..4fbb4a29aad3 100755 --- a/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh +++ b/tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh @@ -5,9 +5,13 @@ # Carsten Haitzler , 2021 TEST="unroll_loop_thread" + +# shellcheck source=../lib/coresight.sh . "$(dirname $0)"/../lib/coresight.sh + ARGS="10" DATV="10" +# shellcheck disable=SC2153 DATA="$DATD/perf-$TEST-$DATV.data" perf record $PERFRECOPT -o "$DATA" "$BIN" $ARGS diff --git a/tools/perf/tests/shell/lib/coresight.sh b/tools/perf/tests/shell/lib/coresight.sh index 6c3d34ec64d8..11ed2c25ed91 100644 --- a/tools/perf/tests/shell/lib/coresight.sh +++ b/tools/perf/tests/shell/lib/coresight.sh @@ -17,6 +17,8 @@ DIR="$TOOLS/$TEST" BIN="$DIR/$TEST" # If the test tool/binary does not exist and is executable then skip the test if ! test -x "$BIN"; then exit 2; fi +# If CoreSight is not available, skip the test +perf list cs_etm | grep -q cs_etm || exit 2 DATD="." # If the data dir env is set then make the data dir use that instead of ./ if test -n "$PERF_TEST_CORESIGHT_DATADIR"; then diff --git a/tools/perf/tests/shell/lock_contention.sh b/tools/perf/tests/shell/lock_contention.sh index d120e83db7d9..c1ec5762215b 100755 --- a/tools/perf/tests/shell/lock_contention.sh +++ b/tools/perf/tests/shell/lock_contention.sh @@ -32,6 +32,13 @@ check() { err=2 exit fi + + # shellcheck disable=SC2046 + if [ `nproc` -lt 4 ]; then + echo "[Skip] Low number of CPUs (`nproc`), lock event cannot be triggered certainly" + err=2 + exit + fi } test_record() @@ -123,6 +130,24 @@ test_aggr_addr() fi } +test_aggr_cgroup() +{ + echo "Testing perf lock contention --lock-cgroup" + + if ! perf lock con -b true > /dev/null 2>&1 ; then + echo "[Skip] No BPF support" + return + fi + + # the perf lock contention output goes to the stderr + perf lock con -a -b -g -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} + if [ "$(cat "${result}" | wc -l)" != "1" ]; then + echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)" + err=1 + exit + fi +} + test_type_filter() { echo "Testing perf lock contention --type-filter (w/ spinlock)" @@ -232,6 +257,31 @@ test_aggr_task_stack_filter() exit fi } +test_cgroup_filter() +{ + echo "Testing perf lock contention --cgroup-filter" + + if ! perf lock con -b true > /dev/null 2>&1 ; then + echo "[Skip] No BPF support" + return + fi + + perf lock con -a -b -g -E 1 -F wait_total -q -- perf bench sched messaging > /dev/null 2> ${result} + if [ "$(cat "${result}" | wc -l)" != "1" ]; then + echo "[Fail] BPF result should have a cgroup result:" "$(cat "${result}")" + err=1 + exit + fi + + cgroup=$(cat "${result}" | awk '{ print $3 }') + perf lock con -a -b -g -E 1 -G "${cgroup}" -q -- perf bench sched messaging > /dev/null 2> ${result} + if [ "$(cat "${result}" | wc -l)" != "1" ]; then + echo "[Fail] BPF result should have a result with cgroup filter:" "$(cat "${cgroup}")" + err=1 + exit + fi +} + test_csv_output() { @@ -275,10 +325,12 @@ test_bpf test_record_concurrent test_aggr_task test_aggr_addr +test_aggr_cgroup test_type_filter test_lock_filter test_stack_filter test_aggr_task_stack_filter +test_cgroup_filter test_csv_output exit ${err} diff --git a/tools/perf/tests/shell/probe_vfs_getname.sh b/tools/perf/tests/shell/probe_vfs_getname.sh index 871243d6d03a..554e12e83c55 100755 --- a/tools/perf/tests/shell/probe_vfs_getname.sh +++ b/tools/perf/tests/shell/probe_vfs_getname.sh @@ -4,10 +4,12 @@ # SPDX-License-Identifier: GPL-2.0 # Arnaldo Carvalho de Melo , 2017 +# shellcheck source=lib/probe.sh . "$(dirname $0)"/lib/probe.sh skip_if_no_perf_probe || exit 2 +# shellcheck source=lib/probe_vfs_getname.sh . "$(dirname $0)"/lib/probe_vfs_getname.sh add_probe_vfs_getname || skip_if_no_debuginfo diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh index 89214a6d9951..eebeea6bdc76 100755 --- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh +++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh @@ -10,7 +10,9 @@ # SPDX-License-Identifier: GPL-2.0 # Arnaldo Carvalho de Melo , 2017 +# shellcheck source=lib/probe.sh . "$(dirname "$0")/lib/probe.sh" +# shellcheck source=lib/probe_vfs_getname.sh . "$(dirname "$0")/lib/probe_vfs_getname.sh" libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g') diff --git a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh index 7f664f1889d9..5eedbe29bba1 100755 --- a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh +++ b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh @@ -9,10 +9,12 @@ # SPDX-License-Identifier: GPL-2.0 # Arnaldo Carvalho de Melo , 2017 +# shellcheck source=lib/probe.sh . "$(dirname "$0")/lib/probe.sh" skip_if_no_perf_probe || exit 2 +# shellcheck source=lib/probe_vfs_getname.sh . "$(dirname "$0")/lib/probe_vfs_getname.sh" record_open_file() { diff --git a/tools/perf/tests/shell/record.sh b/tools/perf/tests/shell/record.sh index 4fbc74805d52..29443b8e8876 100755 --- a/tools/perf/tests/shell/record.sh +++ b/tools/perf/tests/shell/record.sh @@ -5,6 +5,7 @@ set -e shelldir=$(dirname "$0") +# shellcheck source=lib/waiting.sh . "${shelldir}"/lib/waiting.sh err=0 diff --git a/tools/perf/tests/shell/record_offcpu.sh b/tools/perf/tests/shell/record_offcpu.sh index a0d14cd0aa79..a1ef8f0d2b5c 100755 --- a/tools/perf/tests/shell/record_offcpu.sh +++ b/tools/perf/tests/shell/record_offcpu.sh @@ -28,7 +28,7 @@ test_offcpu_priv() { err=2 return fi - if perf record --off-cpu -o /dev/null --quiet true 2>&1 | grep BUILD_BPF_SKEL + if perf version --build-options 2>&1 | grep HAVE_BPF_SKEL | grep -q OFF then echo "off-cpu test [Skipped missing BPF support]" err=2 diff --git a/tools/perf/tests/shell/record_sideband.sh b/tools/perf/tests/shell/record_sideband.sh new file mode 100755 index 000000000000..ac70ac27d590 --- /dev/null +++ b/tools/perf/tests/shell/record_sideband.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# perf record sideband tests +# SPDX-License-Identifier: GPL-2.0 + +set -e + +err=0 +perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) + +cleanup() +{ + rm -rf ${perfdata} + trap - EXIT TERM INT +} + +trap_cleanup() +{ + cleanup + exit 1 +} +trap trap_cleanup EXIT TERM INT + +can_cpu_wide() +{ + if ! perf record -o ${perfdata} -BN --no-bpf-event -C $1 true > /dev/null 2>&1 + then + echo "record sideband test [Skipped cannot record cpu$1]" + err=2 + fi + + rm -f ${perfdata} + return $err +} + +test_system_wide_tracking() +{ + # Need CPU 0 and CPU 1 + can_cpu_wide 0 || return 0 + can_cpu_wide 1 || return 0 + + # Record on CPU 0 a task running on CPU 1 + perf record -BN --no-bpf-event -o ${perfdata} -C 0 -- taskset --cpu-list 1 true + + # Should get MMAP events from CPU 1 + mmap_cnt=`perf script -i ${perfdata} --show-mmap-events -C 1 2>/dev/null | grep MMAP | wc -l` + + if [ ${mmap_cnt} -gt 0 ] ; then + return 0 + fi + + echo "Failed to record MMAP events on CPU 1 when tracing CPU 0" + return 1 +} + +test_system_wide_tracking + +cleanup +exit $err diff --git a/tools/perf/tests/shell/stat+csv_output.sh b/tools/perf/tests/shell/stat+csv_output.sh index d890eb26e914..f1818fa6d9ce 100755 --- a/tools/perf/tests/shell/stat+csv_output.sh +++ b/tools/perf/tests/shell/stat+csv_output.sh @@ -6,6 +6,7 @@ set -e +# shellcheck source=lib/stat_output.sh . "$(dirname $0)"/lib/stat_output.sh csv_sep=@ diff --git a/tools/perf/tests/shell/stat+csv_summary.sh b/tools/perf/tests/shell/stat+csv_summary.sh index 8bae9c8a835e..323123ff4d19 100755 --- a/tools/perf/tests/shell/stat+csv_summary.sh +++ b/tools/perf/tests/shell/stat+csv_summary.sh @@ -10,7 +10,7 @@ set -e # perf stat -e cycles -x' ' -I1000 --interval-count 1 --summary 2>&1 | \ grep -e summary | \ -while read summary _num _event _run _pct +while read summary _ _ _ _ do if [ $summary != "summary" ]; then exit 1 @@ -23,7 +23,7 @@ done # perf stat -e cycles -x' ' -I1000 --interval-count 1 --summary --no-csv-summary 2>&1 | \ grep -e summary | \ -while read _num _event _run _pct +while read _ _ _ _ do exit 1 done diff --git a/tools/perf/tests/shell/stat+shadow_stat.sh b/tools/perf/tests/shell/stat+shadow_stat.sh index a1918a15e36a..0c7d79a230ea 100755 --- a/tools/perf/tests/shell/stat+shadow_stat.sh +++ b/tools/perf/tests/shell/stat+shadow_stat.sh @@ -4,6 +4,8 @@ set -e +THRESHOLD=0.015 + # skip if system-wide mode is forbidden perf stat -a true > /dev/null 2>&1 || exit 2 @@ -14,7 +16,7 @@ test_global_aggr() { perf stat -a --no-big-num -e cycles,instructions sleep 1 2>&1 | \ grep -e cycles -e instructions | \ - while read num evt _hash ipc rest + while read num evt _ ipc rest do # skip not counted events if [ "$num" = " $3)}'` + + if [ $diff -eq 1 ]; then + echo "IPC is different: $res != $ipc ($num / $cyc)" + exit 1 + fi + + echo "Warning: Difference of IPC is under the threshold" fi done } @@ -45,7 +55,7 @@ test_no_aggr() { perf stat -a -A --no-big-num -e cycles,instructions sleep 1 2>&1 | \ grep ^CPU | \ - while read cpu num evt _hash ipc rest + while read cpu num evt _ ipc rest do # skip not counted events if [ "$num" = " $3)}'` + + if [ $diff -eq 1 ]; then + echo "IPC is different: $res != $ipc ($num / $cyc)" + exit 1 + fi + + echo "Warning: Difference of IPC is under the threshold" fi done } diff --git a/tools/perf/tests/shell/stat+std_output.sh b/tools/perf/tests/shell/stat+std_output.sh index fb2b10547a11..4fcdd1a9142c 100755 --- a/tools/perf/tests/shell/stat+std_output.sh +++ b/tools/perf/tests/shell/stat+std_output.sh @@ -6,6 +6,7 @@ set -e +# shellcheck source=lib/stat_output.sh . "$(dirname $0)"/lib/stat_output.sh stat_output=$(mktemp /tmp/__perf_test.stat_output.std.XXXXX) diff --git a/tools/perf/tests/shell/stat_all_metricgroups.sh b/tools/perf/tests/shell/stat_all_metricgroups.sh index cb35e488809a..55ef9c9ded2d 100755 --- a/tools/perf/tests/shell/stat_all_metricgroups.sh +++ b/tools/perf/tests/shell/stat_all_metricgroups.sh @@ -4,9 +4,21 @@ set -e -for m in $(perf list --raw-dump metricgroups); do +ParanoidAndNotRoot() +{ + [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ] +} + +system_wide_flag="-a" +if ParanoidAndNotRoot 0 +then + system_wide_flag="" +fi + +for m in $(perf list --raw-dump metricgroups) +do echo "Testing $m" - perf stat -M "$m" -a true + perf stat -M "$m" $system_wide_flag sleep 0.01 done exit 0 diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh index f1bf5621160f..65dd85207125 100755 --- a/tools/perf/tests/shell/test_arm_coresight.sh +++ b/tools/perf/tests/shell/test_arm_coresight.sh @@ -136,7 +136,9 @@ arm_cs_iterate_devices() { arm_cs_etm_traverse_path_test() { # Iterate for every ETM device - for dev in /sys/bus/coresight/devices/etm*; do + for dev in /sys/bus/event_source/devices/cs_etm/cpu*; do + # Canonicalize the path + dev=`readlink -f $dev` # Find the ETM device belonging to which CPU cpu=`cat $dev/cpu` diff --git a/tools/perf/tests/shell/test_intel_pt.sh b/tools/perf/tests/shell/test_intel_pt.sh index 3a8b9bffa022..723ec501f99a 100755 --- a/tools/perf/tests/shell/test_intel_pt.sh +++ b/tools/perf/tests/shell/test_intel_pt.sh @@ -8,6 +8,7 @@ set -e perf list | grep -q 'intel_pt//' || exit 2 shelldir=$(dirname "$0") +# shellcheck source=lib/waiting.sh . "${shelldir}"/lib/waiting.sh skip_cnt=0 diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh index 4014487cf4d9..3146a1eece07 100755 --- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh +++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh @@ -10,6 +10,7 @@ # SPDX-License-Identifier: GPL-2.0 # Arnaldo Carvalho de Melo , 2017 +# shellcheck source=lib/probe.sh . "$(dirname $0)"/lib/probe.sh skip_if_no_perf_probe || exit 2 diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index f33cfc3c19a4..b394f3ac2d66 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -145,6 +145,7 @@ DECLARE_SUITE(dlfilter); DECLARE_SUITE(sigtrap); DECLARE_SUITE(event_groups); DECLARE_SUITE(symbols); +DECLARE_SUITE(util); /* * PowerPC and S390 do not support creation of instruction breakpoints using the diff --git a/tools/perf/tests/thread-maps-share.c b/tools/perf/tests/thread-maps-share.c index faf980b26252..7fa6f7c568e2 100644 --- a/tools/perf/tests/thread-maps-share.c +++ b/tools/perf/tests/thread-maps-share.c @@ -46,9 +46,9 @@ static int test__thread_maps_share(struct test_suite *test __maybe_unused, int s TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(maps__refcnt(maps)), 4); /* test the maps pointer is shared */ - TEST_ASSERT_VAL("maps don't match", RC_CHK_ACCESS(maps) == RC_CHK_ACCESS(thread__maps(t1))); - TEST_ASSERT_VAL("maps don't match", RC_CHK_ACCESS(maps) == RC_CHK_ACCESS(thread__maps(t2))); - TEST_ASSERT_VAL("maps don't match", RC_CHK_ACCESS(maps) == RC_CHK_ACCESS(thread__maps(t3))); + TEST_ASSERT_VAL("maps don't match", RC_CHK_EQUAL(maps, thread__maps(t1))); + TEST_ASSERT_VAL("maps don't match", RC_CHK_EQUAL(maps, thread__maps(t2))); + TEST_ASSERT_VAL("maps don't match", RC_CHK_EQUAL(maps, thread__maps(t3))); /* * Verify the other leader was created by previous call. @@ -73,8 +73,7 @@ static int test__thread_maps_share(struct test_suite *test __maybe_unused, int s other_maps = thread__maps(other); TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(maps__refcnt(other_maps)), 2); - TEST_ASSERT_VAL("maps don't match", RC_CHK_ACCESS(other_maps) == - RC_CHK_ACCESS(thread__maps(other_leader))); + TEST_ASSERT_VAL("maps don't match", RC_CHK_EQUAL(other_maps, thread__maps(other_leader))); /* release thread group */ thread__put(t3); diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c new file mode 100644 index 000000000000..6366db5cbf8c --- /dev/null +++ b/tools/perf/tests/util.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "tests.h" +#include "util/debug.h" + +#include +#include +#include + +static int test_strreplace(char needle, const char *haystack, + const char *replace, const char *expected) +{ + char *new = strreplace_chars(needle, haystack, replace); + int ret = strcmp(new, expected); + + free(new); + return ret == 0; +} + +static int test__util(struct test_suite *t __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_VAL("empty string", test_strreplace(' ', "", "123", "")); + TEST_ASSERT_VAL("no match", test_strreplace('5', "123", "4", "123")); + TEST_ASSERT_VAL("replace 1", test_strreplace('3', "123", "4", "124")); + TEST_ASSERT_VAL("replace 2", test_strreplace('a', "abcabc", "ef", "efbcefbc")); + TEST_ASSERT_VAL("replace long", test_strreplace('a', "abcabc", "longlong", + "longlongbclonglongbc")); + + return 0; +} + +DEFINE_SUITE("util", util); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 70db5a717905..f4812b226818 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2416,12 +2416,12 @@ close_file_and_continue: struct popup_action { unsigned long time; struct thread *thread; + struct evsel *evsel; + int (*fn)(struct hist_browser *browser, struct popup_action *act); struct map_symbol ms; int socket; - struct evsel *evsel; enum rstype rstype; - int (*fn)(struct hist_browser *browser, struct popup_action *act); }; static int @@ -3302,7 +3302,7 @@ do_hotkey: // key came straight from options ui__popup_menu() &options[nr_options], &bi->to.ms, bi->to.al_addr); - } else { + } else if (browser->he_selection) { nr_options += add_annotate_opt(browser, &actions[nr_options], &options[nr_options], diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 2f76230958ad..fb661c48992f 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -49,6 +49,7 @@ perf-y += dso.o perf-y += dsos.o perf-y += symbol.o perf-y += symbol_fprintf.o +perf-y += map_symbol.o perf-y += color.o perf-y += color_config.o perf-y += metricgroup.o @@ -165,6 +166,7 @@ endif ifeq ($(CONFIG_LIBTRACEEVENT),y) perf-$(CONFIG_PERF_BPF_SKEL) += bpf_kwork.o + perf-$(CONFIG_PERF_BPF_SKEL) += bpf_kwork_top.o endif perf-$(CONFIG_LIBELF) += symbol-elf.o diff --git a/tools/perf/util/arm-spe.h b/tools/perf/util/arm-spe.h index 98d3235781c3..4f4900c18f3e 100644 --- a/tools/perf/util/arm-spe.h +++ b/tools/perf/util/arm-spe.h @@ -27,5 +27,7 @@ struct auxtrace_record *arm_spe_recording_init(int *err, int arm_spe_process_auxtrace_info(union perf_event *event, struct perf_session *session); -struct perf_event_attr *arm_spe_pmu_default_config(struct perf_pmu *arm_spe_pmu); +void arm_spe_pmu_default_config(const struct perf_pmu *arm_spe_pmu, + struct perf_event_attr *attr); + #endif diff --git a/tools/perf/util/bpf-filter.y b/tools/perf/util/bpf-filter.y index 5dfa948fc986..0e4d6de3c2ad 100644 --- a/tools/perf/util/bpf-filter.y +++ b/tools/perf/util/bpf-filter.y @@ -3,6 +3,10 @@ %{ +#ifndef NDEBUG +#define YYDEBUG 1 +#endif + #include #include #include diff --git a/tools/perf/util/bpf_counter.c b/tools/perf/util/bpf_counter.c index 6732cbbcf9b3..7f9b0e46e008 100644 --- a/tools/perf/util/bpf_counter.c +++ b/tools/perf/util/bpf_counter.c @@ -104,7 +104,7 @@ static int bpf_program_profiler_load_one(struct evsel *evsel, u32 prog_id) struct bpf_prog_profiler_bpf *skel; struct bpf_counter *counter; struct bpf_program *prog; - char *prog_name; + char *prog_name = NULL; int prog_fd; int err; @@ -155,10 +155,12 @@ static int bpf_program_profiler_load_one(struct evsel *evsel, u32 prog_id) assert(skel != NULL); counter->skel = skel; list_add(&counter->list, &evsel->bpf_counter_list); + free(prog_name); close(prog_fd); return 0; err_out: bpf_prog_profiler_bpf__destroy(skel); + free(prog_name); free(counter); close(prog_fd); return -1; @@ -180,6 +182,7 @@ static int bpf_program_profiler__load(struct evsel *evsel, struct target *target (*p != '\0' && *p != ',')) { pr_err("Failed to parse bpf prog ids %s\n", target->bpf_str); + free(bpf_str_); return -1; } diff --git a/tools/perf/util/bpf_kwork_top.c b/tools/perf/util/bpf_kwork_top.c new file mode 100644 index 000000000000..035e02272790 --- /dev/null +++ b/tools/perf/util/bpf_kwork_top.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * bpf_kwork_top.c + * + * Copyright (c) 2022 Huawei Inc, Yang Jihong + */ + +#include +#include +#include +#include +#include + +#include + +#include "util/debug.h" +#include "util/evsel.h" +#include "util/kwork.h" + +#include +#include + +#include "util/bpf_skel/kwork_top.skel.h" + +/* + * This should be in sync with "util/kwork_top.bpf.c" + */ +#define MAX_COMMAND_LEN 16 + +struct time_data { + __u64 timestamp; +}; + +struct work_data { + __u64 runtime; +}; + +struct task_data { + __u32 tgid; + __u32 is_kthread; + char comm[MAX_COMMAND_LEN]; +}; + +struct work_key { + __u32 type; + __u32 pid; + __u64 task_p; +}; + +struct task_key { + __u32 pid; + __u32 cpu; +}; + +struct kwork_class_bpf { + struct kwork_class *class; + void (*load_prepare)(void); +}; + +static struct kwork_top_bpf *skel; + +void perf_kwork__top_start(void) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + skel->bss->from_timestamp = (u64)ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; + skel->bss->enabled = 1; + pr_debug("perf kwork top start at: %lld\n", skel->bss->from_timestamp); +} + +void perf_kwork__top_finish(void) +{ + struct timespec ts; + + skel->bss->enabled = 0; + clock_gettime(CLOCK_MONOTONIC, &ts); + skel->bss->to_timestamp = (u64)ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec; + pr_debug("perf kwork top finish at: %lld\n", skel->bss->to_timestamp); +} + +static void irq_load_prepare(void) +{ + bpf_program__set_autoload(skel->progs.on_irq_handler_entry, true); + bpf_program__set_autoload(skel->progs.on_irq_handler_exit, true); +} + +static struct kwork_class_bpf kwork_irq_bpf = { + .load_prepare = irq_load_prepare, +}; + +static void softirq_load_prepare(void) +{ + bpf_program__set_autoload(skel->progs.on_softirq_entry, true); + bpf_program__set_autoload(skel->progs.on_softirq_exit, true); +} + +static struct kwork_class_bpf kwork_softirq_bpf = { + .load_prepare = softirq_load_prepare, +}; + +static void sched_load_prepare(void) +{ + bpf_program__set_autoload(skel->progs.on_switch, true); +} + +static struct kwork_class_bpf kwork_sched_bpf = { + .load_prepare = sched_load_prepare, +}; + +static struct kwork_class_bpf * +kwork_class_bpf_supported_list[KWORK_CLASS_MAX] = { + [KWORK_CLASS_IRQ] = &kwork_irq_bpf, + [KWORK_CLASS_SOFTIRQ] = &kwork_softirq_bpf, + [KWORK_CLASS_SCHED] = &kwork_sched_bpf, +}; + +static bool valid_kwork_class_type(enum kwork_class_type type) +{ + return type >= 0 && type < KWORK_CLASS_MAX; +} + +static int setup_filters(struct perf_kwork *kwork) +{ + u8 val = 1; + int i, nr_cpus, fd; + struct perf_cpu_map *map; + + if (kwork->cpu_list) { + fd = bpf_map__fd(skel->maps.kwork_top_cpu_filter); + if (fd < 0) { + pr_debug("Invalid cpu filter fd\n"); + return -1; + } + + map = perf_cpu_map__new(kwork->cpu_list); + if (!map) { + pr_debug("Invalid cpu_list\n"); + return -1; + } + + nr_cpus = libbpf_num_possible_cpus(); + for (i = 0; i < perf_cpu_map__nr(map); i++) { + struct perf_cpu cpu = perf_cpu_map__cpu(map, i); + + if (cpu.cpu >= nr_cpus) { + perf_cpu_map__put(map); + pr_err("Requested cpu %d too large\n", cpu.cpu); + return -1; + } + bpf_map_update_elem(fd, &cpu.cpu, &val, BPF_ANY); + } + perf_cpu_map__put(map); + + skel->bss->has_cpu_filter = 1; + } + + return 0; +} + +int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused) +{ + struct bpf_program *prog; + struct kwork_class *class; + struct kwork_class_bpf *class_bpf; + enum kwork_class_type type; + + skel = kwork_top_bpf__open(); + if (!skel) { + pr_debug("Failed to open kwork top skeleton\n"); + return -1; + } + + /* + * set all progs to non-autoload, + * then set corresponding progs according to config + */ + bpf_object__for_each_program(prog, skel->obj) + bpf_program__set_autoload(prog, false); + + list_for_each_entry(class, &kwork->class_list, list) { + type = class->type; + if (!valid_kwork_class_type(type) || + !kwork_class_bpf_supported_list[type]) { + pr_err("Unsupported bpf trace class %s\n", class->name); + goto out; + } + + class_bpf = kwork_class_bpf_supported_list[type]; + class_bpf->class = class; + + if (class_bpf->load_prepare) + class_bpf->load_prepare(); + } + + if (kwork_top_bpf__load(skel)) { + pr_debug("Failed to load kwork top skeleton\n"); + goto out; + } + + if (setup_filters(kwork)) + goto out; + + if (kwork_top_bpf__attach(skel)) { + pr_debug("Failed to attach kwork top skeleton\n"); + goto out; + } + + return 0; + +out: + kwork_top_bpf__destroy(skel); + return -1; +} + +static void read_task_info(struct kwork_work *work) +{ + int fd; + struct task_data data; + struct task_key key = { + .pid = work->id, + .cpu = work->cpu, + }; + + fd = bpf_map__fd(skel->maps.kwork_top_tasks); + if (fd < 0) { + pr_debug("Invalid top tasks map fd\n"); + return; + } + + if (!bpf_map_lookup_elem(fd, &key, &data)) { + work->tgid = data.tgid; + work->is_kthread = data.is_kthread; + work->name = strdup(data.comm); + } +} +static int add_work(struct perf_kwork *kwork, struct work_key *key, + struct work_data *data, int cpu) +{ + struct kwork_class_bpf *bpf_trace; + struct kwork_work *work; + struct kwork_work tmp = { + .id = key->pid, + .cpu = cpu, + .name = NULL, + }; + enum kwork_class_type type = key->type; + + if (!valid_kwork_class_type(type)) { + pr_debug("Invalid class type %d to add work\n", type); + return -1; + } + + bpf_trace = kwork_class_bpf_supported_list[type]; + tmp.class = bpf_trace->class; + + work = perf_kwork_add_work(kwork, tmp.class, &tmp); + if (!work) + return -1; + + work->total_runtime = data->runtime; + read_task_info(work); + + return 0; +} + +int perf_kwork__top_read_bpf(struct perf_kwork *kwork) +{ + int i, fd, nr_cpus; + struct work_data *data; + struct work_key key, prev; + + fd = bpf_map__fd(skel->maps.kwork_top_works); + if (fd < 0) { + pr_debug("Invalid top runtime fd\n"); + return -1; + } + + nr_cpus = libbpf_num_possible_cpus(); + data = calloc(nr_cpus, sizeof(struct work_data)); + if (!data) + return -1; + + memset(&prev, 0, sizeof(prev)); + while (!bpf_map_get_next_key(fd, &prev, &key)) { + if ((bpf_map_lookup_elem(fd, &key, data)) != 0) { + pr_debug("Failed to lookup top elem\n"); + return -1; + } + + for (i = 0; i < nr_cpus; i++) { + if (data[i].runtime == 0) + continue; + + if (add_work(kwork, &key, &data[i], i)) + return -1; + } + prev = key; + } + free(data); + + return 0; +} + +void perf_kwork__top_cleanup_bpf(void) +{ + kwork_top_bpf__destroy(skel); +} diff --git a/tools/perf/util/bpf_lock_contention.c b/tools/perf/util/bpf_lock_contention.c index e7dddf0127bc..e105245eb905 100644 --- a/tools/perf/util/bpf_lock_contention.c +++ b/tools/perf/util/bpf_lock_contention.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include "util/cgroup.h" #include "util/debug.h" #include "util/evlist.h" #include "util/machine.h" @@ -20,7 +21,7 @@ static struct lock_contention_bpf *skel; int lock_contention_prepare(struct lock_contention *con) { int i, fd; - int ncpus = 1, ntasks = 1, ntypes = 1, naddrs = 1; + int ncpus = 1, ntasks = 1, ntypes = 1, naddrs = 1, ncgrps = 1; struct evlist *evlist = con->evlist; struct target *target = con->target; @@ -50,6 +51,8 @@ int lock_contention_prepare(struct lock_contention *con) ntasks = perf_thread_map__nr(evlist->core.threads); if (con->filters->nr_types) ntypes = con->filters->nr_types; + if (con->filters->nr_cgrps) + ncgrps = con->filters->nr_cgrps; /* resolve lock name filters to addr */ if (con->filters->nr_syms) { @@ -84,6 +87,7 @@ int lock_contention_prepare(struct lock_contention *con) bpf_map__set_max_entries(skel->maps.task_filter, ntasks); bpf_map__set_max_entries(skel->maps.type_filter, ntypes); bpf_map__set_max_entries(skel->maps.addr_filter, naddrs); + bpf_map__set_max_entries(skel->maps.cgroup_filter, ncgrps); if (lock_contention_bpf__load(skel) < 0) { pr_err("Failed to load lock-contention BPF skeleton\n"); @@ -145,12 +149,29 @@ int lock_contention_prepare(struct lock_contention *con) bpf_map_update_elem(fd, &con->filters->addrs[i], &val, BPF_ANY); } + if (con->filters->nr_cgrps) { + u8 val = 1; + + skel->bss->has_cgroup = 1; + fd = bpf_map__fd(skel->maps.cgroup_filter); + + for (i = 0; i < con->filters->nr_cgrps; i++) + bpf_map_update_elem(fd, &con->filters->cgrps[i], &val, BPF_ANY); + } + /* these don't work well if in the rodata section */ skel->bss->stack_skip = con->stack_skip; skel->bss->aggr_mode = con->aggr_mode; skel->bss->needs_callstack = con->save_callstack; skel->bss->lock_owner = con->owner; + if (con->aggr_mode == LOCK_AGGR_CGROUP) { + if (cgroup_is_v2("perf_event")) + skel->bss->use_cgroup_v2 = 1; + + read_all_cgroups(&con->cgroups); + } + bpf_program__set_autoload(skel->progs.collect_lock_syms, false); lock_contention_bpf__attach(skel); @@ -209,12 +230,12 @@ static const char *lock_contention_get_name(struct lock_contention *con, return "siglock"; /* global locks with symbols */ - sym = machine__find_kernel_symbol(machine, key->lock_addr, &kmap); + sym = machine__find_kernel_symbol(machine, key->lock_addr_or_cgroup, &kmap); if (sym) return sym->name; /* try semi-global locks collected separately */ - if (!bpf_map_lookup_elem(lock_fd, &key->lock_addr, &flags)) { + if (!bpf_map_lookup_elem(lock_fd, &key->lock_addr_or_cgroup, &flags)) { if (flags == LOCK_CLASS_RQLOCK) return "rq_lock"; } @@ -222,6 +243,17 @@ static const char *lock_contention_get_name(struct lock_contention *con, return ""; } + if (con->aggr_mode == LOCK_AGGR_CGROUP) { + u64 cgrp_id = key->lock_addr_or_cgroup; + struct cgroup *cgrp = __cgroup__find(&con->cgroups, cgrp_id); + + if (cgrp) + return cgrp->name; + + snprintf(name_buf, sizeof(name_buf), "cgroup:%lu", cgrp_id); + return name_buf; + } + /* LOCK_AGGR_CALLER: skip lock internal functions */ while (machine__is_lock_function(machine, stack_trace[idx]) && idx < con->max_stack - 1) @@ -313,7 +345,8 @@ int lock_contention_read(struct lock_contention *con) ls_key = key.pid; break; case LOCK_AGGR_ADDR: - ls_key = key.lock_addr; + case LOCK_AGGR_CGROUP: + ls_key = key.lock_addr_or_cgroup; break; default: goto next; @@ -364,12 +397,20 @@ next: return err; } -int lock_contention_finish(void) +int lock_contention_finish(struct lock_contention *con) { if (skel) { skel->bss->enabled = 0; lock_contention_bpf__destroy(skel); } + while (!RB_EMPTY_ROOT(&con->cgroups)) { + struct rb_node *node = rb_first(&con->cgroups); + struct cgroup *cgrp = rb_entry(node, struct cgroup, node); + + rb_erase(node, &con->cgroups); + cgroup__put(cgrp); + } + return 0; } diff --git a/tools/perf/util/bpf_off_cpu.c b/tools/perf/util/bpf_off_cpu.c index 01f70b8e705a..6af36142dc5a 100644 --- a/tools/perf/util/bpf_off_cpu.c +++ b/tools/perf/util/bpf_off_cpu.c @@ -98,28 +98,31 @@ static void off_cpu_finish(void *arg __maybe_unused) /* v5.18 kernel added prev_state arg, so it needs to check the signature */ static void check_sched_switch_args(void) { - const struct btf *btf = bpf_object__btf(skel->obj); + struct btf *btf = btf__load_vmlinux_btf(); const struct btf_type *t1, *t2, *t3; u32 type_id; type_id = btf__find_by_name_kind(btf, "btf_trace_sched_switch", BTF_KIND_TYPEDEF); if ((s32)type_id < 0) - return; + goto cleanup; t1 = btf__type_by_id(btf, type_id); if (t1 == NULL) - return; + goto cleanup; t2 = btf__type_by_id(btf, t1->type); if (t2 == NULL || !btf_is_ptr(t2)) - return; + goto cleanup; t3 = btf__type_by_id(btf, t2->type); - if (t3 && btf_is_func_proto(t3) && btf_vlen(t3) == 4) { + /* btf_trace func proto has one more argument for the context */ + if (t3 && btf_is_func_proto(t3) && btf_vlen(t3) == 5) { /* new format: pass prev_state as 4th arg */ skel->rodata->has_prev_state = true; } +cleanup: + btf__free(btf); } int off_cpu_prepare(struct evlist *evlist, struct target *target, diff --git a/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c b/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c index 939ec769bf4a..52c270330ae0 100644 --- a/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c +++ b/tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c @@ -153,7 +153,7 @@ static inline unsigned int augmented_arg__read_str(struct augmented_arg *augmented_arg, const void *arg, unsigned int arg_len) { unsigned int augmented_len = sizeof(*augmented_arg); - int string_len = bpf_probe_read_str(&augmented_arg->value, arg_len, arg); + int string_len = bpf_probe_read_user_str(&augmented_arg->value, arg_len, arg); augmented_arg->size = augmented_arg->err = 0; /* @@ -203,7 +203,7 @@ int sys_enter_connect(struct syscall_enter_args *args) _Static_assert(is_power_of_2(sizeof(augmented_args->saddr)), "sizeof(augmented_args->saddr) needs to be a power of two"); socklen &= sizeof(augmented_args->saddr) - 1; - bpf_probe_read(&augmented_args->saddr, socklen, sockaddr_arg); + bpf_probe_read_user(&augmented_args->saddr, socklen, sockaddr_arg); return augmented__output(args, augmented_args, len + socklen); } @@ -221,7 +221,7 @@ int sys_enter_sendto(struct syscall_enter_args *args) socklen &= sizeof(augmented_args->saddr) - 1; - bpf_probe_read(&augmented_args->saddr, socklen, sockaddr_arg); + bpf_probe_read_user(&augmented_args->saddr, socklen, sockaddr_arg); return augmented__output(args, augmented_args, len + socklen); } @@ -311,7 +311,7 @@ int sys_enter_perf_event_open(struct syscall_enter_args *args) if (augmented_args == NULL) goto failure; - if (bpf_probe_read(&augmented_args->__data, sizeof(*attr), attr) < 0) + if (bpf_probe_read_user(&augmented_args->__data, sizeof(*attr), attr) < 0) goto failure; attr_read = (const struct perf_event_attr_size *)augmented_args->__data; @@ -325,7 +325,7 @@ int sys_enter_perf_event_open(struct syscall_enter_args *args) goto failure; // Now that we read attr->size and tested it against the size limits, read it completely - if (bpf_probe_read(&augmented_args->__data, size, attr) < 0) + if (bpf_probe_read_user(&augmented_args->__data, size, attr) < 0) goto failure; return augmented__output(args, augmented_args, len + size); @@ -347,7 +347,7 @@ int sys_enter_clock_nanosleep(struct syscall_enter_args *args) if (size > sizeof(augmented_args->__data)) goto failure; - bpf_probe_read(&augmented_args->__data, size, rqtp_arg); + bpf_probe_read_user(&augmented_args->__data, size, rqtp_arg); return augmented__output(args, augmented_args, len + size); failure: @@ -385,7 +385,7 @@ int sys_enter(struct syscall_enter_args *args) if (augmented_args == NULL) return 1; - bpf_probe_read(&augmented_args->args, sizeof(augmented_args->args), args); + bpf_probe_read_kernel(&augmented_args->args, sizeof(augmented_args->args), args); /* * Jump to syscall specific augmenter, even if the default one, @@ -406,7 +406,7 @@ int sys_exit(struct syscall_exit_args *args) if (pid_filter__has(&pids_filtered, getpid())) return 0; - bpf_probe_read(&exit_args, sizeof(exit_args), args); + bpf_probe_read_kernel(&exit_args, sizeof(exit_args), args); /* * Jump to syscall specific return augmenter, even if the default one, * "!raw_syscalls:unaugmented" that will just return 1 to return the diff --git a/tools/perf/util/bpf_skel/kwork_top.bpf.c b/tools/perf/util/bpf_skel/kwork_top.bpf.c new file mode 100644 index 000000000000..84c15ccbab44 --- /dev/null +++ b/tools/perf/util/bpf_skel/kwork_top.bpf.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright (c) 2022, Huawei + +#include "vmlinux.h" +#include +#include +#include + +/* + * This should be in sync with "util/kwork.h" + */ +enum kwork_class_type { + KWORK_CLASS_IRQ, + KWORK_CLASS_SOFTIRQ, + KWORK_CLASS_WORKQUEUE, + KWORK_CLASS_SCHED, + KWORK_CLASS_MAX, +}; + +#define MAX_ENTRIES 102400 +#define MAX_NR_CPUS 2048 +#define PF_KTHREAD 0x00200000 +#define MAX_COMMAND_LEN 16 + +struct time_data { + __u64 timestamp; +}; + +struct work_data { + __u64 runtime; +}; + +struct task_data { + __u32 tgid; + __u32 is_kthread; + char comm[MAX_COMMAND_LEN]; +}; + +struct work_key { + __u32 type; + __u32 pid; + __u64 task_p; +}; + +struct task_key { + __u32 pid; + __u32 cpu; +}; + +struct { + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct time_data); +} kwork_top_task_time SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_HASH); + __uint(key_size, sizeof(struct work_key)); + __uint(value_size, sizeof(struct time_data)); + __uint(max_entries, MAX_ENTRIES); +} kwork_top_irq_time SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(struct task_key)); + __uint(value_size, sizeof(struct task_data)); + __uint(max_entries, MAX_ENTRIES); +} kwork_top_tasks SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_HASH); + __uint(key_size, sizeof(struct work_key)); + __uint(value_size, sizeof(struct work_data)); + __uint(max_entries, MAX_ENTRIES); +} kwork_top_works SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(u8)); + __uint(max_entries, MAX_NR_CPUS); +} kwork_top_cpu_filter SEC(".maps"); + +int enabled = 0; + +int has_cpu_filter = 0; + +__u64 from_timestamp = 0; +__u64 to_timestamp = 0; + +static __always_inline int cpu_is_filtered(__u32 cpu) +{ + __u8 *cpu_val; + + if (has_cpu_filter) { + cpu_val = bpf_map_lookup_elem(&kwork_top_cpu_filter, &cpu); + if (!cpu_val) + return 1; + } + + return 0; +} + +static __always_inline void update_task_info(struct task_struct *task, __u32 cpu) +{ + struct task_key key = { + .pid = task->pid, + .cpu = cpu, + }; + + if (!bpf_map_lookup_elem(&kwork_top_tasks, &key)) { + struct task_data data = { + .tgid = task->tgid, + .is_kthread = task->flags & PF_KTHREAD ? 1 : 0, + }; + BPF_CORE_READ_STR_INTO(&data.comm, task, comm); + + bpf_map_update_elem(&kwork_top_tasks, &key, &data, BPF_ANY); + } +} + +static __always_inline void update_work(struct work_key *key, __u64 delta) +{ + struct work_data *data; + + data = bpf_map_lookup_elem(&kwork_top_works, key); + if (data) { + data->runtime += delta; + } else { + struct work_data new_data = { + .runtime = delta, + }; + + bpf_map_update_elem(&kwork_top_works, key, &new_data, BPF_ANY); + } +} + +static void on_sched_out(struct task_struct *task, __u64 ts, __u32 cpu) +{ + __u64 delta; + struct time_data *pelem; + + pelem = bpf_task_storage_get(&kwork_top_task_time, task, NULL, 0); + if (pelem) + delta = ts - pelem->timestamp; + else + delta = ts - from_timestamp; + + struct work_key key = { + .type = KWORK_CLASS_SCHED, + .pid = task->pid, + .task_p = (__u64)task, + }; + + update_work(&key, delta); + update_task_info(task, cpu); +} + +static void on_sched_in(struct task_struct *task, __u64 ts) +{ + struct time_data *pelem; + + pelem = bpf_task_storage_get(&kwork_top_task_time, task, NULL, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (pelem) + pelem->timestamp = ts; +} + +SEC("tp_btf/sched_switch") +int on_switch(u64 *ctx) +{ + struct task_struct *prev, *next; + + prev = (struct task_struct *)ctx[1]; + next = (struct task_struct *)ctx[2]; + + if (!enabled) + return 0; + + __u32 cpu = bpf_get_smp_processor_id(); + + if (cpu_is_filtered(cpu)) + return 0; + + __u64 ts = bpf_ktime_get_ns(); + + on_sched_out(prev, ts, cpu); + on_sched_in(next, ts); + + return 0; +} + +SEC("tp_btf/irq_handler_entry") +int on_irq_handler_entry(u64 *cxt) +{ + struct task_struct *task; + + if (!enabled) + return 0; + + __u32 cpu = bpf_get_smp_processor_id(); + + if (cpu_is_filtered(cpu)) + return 0; + + __u64 ts = bpf_ktime_get_ns(); + + task = (struct task_struct *)bpf_get_current_task(); + if (!task) + return 0; + + struct work_key key = { + .type = KWORK_CLASS_IRQ, + .pid = BPF_CORE_READ(task, pid), + .task_p = (__u64)task, + }; + + struct time_data data = { + .timestamp = ts, + }; + + bpf_map_update_elem(&kwork_top_irq_time, &key, &data, BPF_ANY); + + return 0; +} + +SEC("tp_btf/irq_handler_exit") +int on_irq_handler_exit(u64 *cxt) +{ + __u64 delta; + struct task_struct *task; + struct time_data *pelem; + + if (!enabled) + return 0; + + __u32 cpu = bpf_get_smp_processor_id(); + + if (cpu_is_filtered(cpu)) + return 0; + + __u64 ts = bpf_ktime_get_ns(); + + task = (struct task_struct *)bpf_get_current_task(); + if (!task) + return 0; + + struct work_key key = { + .type = KWORK_CLASS_IRQ, + .pid = BPF_CORE_READ(task, pid), + .task_p = (__u64)task, + }; + + pelem = bpf_map_lookup_elem(&kwork_top_irq_time, &key); + if (pelem && pelem->timestamp != 0) + delta = ts - pelem->timestamp; + else + delta = ts - from_timestamp; + + update_work(&key, delta); + + return 0; +} + +SEC("tp_btf/softirq_entry") +int on_softirq_entry(u64 *cxt) +{ + struct task_struct *task; + + if (!enabled) + return 0; + + __u32 cpu = bpf_get_smp_processor_id(); + + if (cpu_is_filtered(cpu)) + return 0; + + __u64 ts = bpf_ktime_get_ns(); + + task = (struct task_struct *)bpf_get_current_task(); + if (!task) + return 0; + + struct work_key key = { + .type = KWORK_CLASS_SOFTIRQ, + .pid = BPF_CORE_READ(task, pid), + .task_p = (__u64)task, + }; + + struct time_data data = { + .timestamp = ts, + }; + + bpf_map_update_elem(&kwork_top_irq_time, &key, &data, BPF_ANY); + + return 0; +} + +SEC("tp_btf/softirq_exit") +int on_softirq_exit(u64 *cxt) +{ + __u64 delta; + struct task_struct *task; + struct time_data *pelem; + + if (!enabled) + return 0; + + __u32 cpu = bpf_get_smp_processor_id(); + + if (cpu_is_filtered(cpu)) + return 0; + + __u64 ts = bpf_ktime_get_ns(); + + task = (struct task_struct *)bpf_get_current_task(); + if (!task) + return 0; + + struct work_key key = { + .type = KWORK_CLASS_SOFTIRQ, + .pid = BPF_CORE_READ(task, pid), + .task_p = (__u64)task, + }; + + pelem = bpf_map_lookup_elem(&kwork_top_irq_time, &key); + if (pelem) + delta = ts - pelem->timestamp; + else + delta = ts - from_timestamp; + + update_work(&key, delta); + + return 0; +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c index 8d3cfbb3cc65..95cd8414f6ef 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -42,6 +42,14 @@ struct { __uint(max_entries, MAX_ENTRIES); } tstamp SEC(".maps"); +/* maintain per-CPU timestamp at the beginning of contention */ +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(struct tstamp_data)); + __uint(max_entries, 1); +} tstamp_cpu SEC(".maps"); + /* actual lock contention statistics */ struct { __uint(type, BPF_MAP_TYPE_HASH); @@ -92,6 +100,13 @@ struct { __uint(max_entries, 1); } addr_filter SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u64)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} cgroup_filter SEC(".maps"); + struct rw_semaphore___old { struct task_struct *owner; } __attribute__((preserve_access_index)); @@ -114,10 +129,14 @@ int has_cpu; int has_task; int has_type; int has_addr; +int has_cgroup; int needs_callstack; int stack_skip; int lock_owner; +int use_cgroup_v2; +int perf_subsys_id = -1; + /* determine the key of lock stat */ int aggr_mode; @@ -130,6 +149,29 @@ int data_fail; int task_map_full; int data_map_full; +static inline __u64 get_current_cgroup_id(void) +{ + struct task_struct *task; + struct cgroup *cgrp; + + if (use_cgroup_v2) + return bpf_get_current_cgroup_id(); + + task = bpf_get_current_task_btf(); + + if (perf_subsys_id == -1) { +#if __has_builtin(__builtin_preserve_enum_value) + perf_subsys_id = bpf_core_enum_value(enum cgroup_subsys_id, + perf_event_cgrp_id); +#else + perf_subsys_id = perf_event_cgrp_id; +#endif + } + + cgrp = BPF_CORE_READ(task, cgroups, subsys[perf_subsys_id], cgroup); + return BPF_CORE_READ(cgrp, kn, id); +} + static inline int can_record(u64 *ctx) { if (has_cpu) { @@ -168,6 +210,15 @@ static inline int can_record(u64 *ctx) return 0; } + if (has_cgroup) { + __u8 *ok; + __u64 cgrp = get_current_cgroup_id(); + + ok = bpf_map_lookup_elem(&cgroup_filter, &cgrp); + if (!ok) + return 0; + } + return 1; } @@ -268,31 +319,58 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags) return 0; } +static inline struct tstamp_data *get_tstamp_elem(__u32 flags) +{ + __u32 pid; + struct tstamp_data *pelem; + + /* Use per-cpu array map for spinlock and rwlock */ + if (flags == (LCB_F_SPIN | LCB_F_READ) || flags == LCB_F_SPIN || + flags == (LCB_F_SPIN | LCB_F_WRITE)) { + __u32 idx = 0; + + pelem = bpf_map_lookup_elem(&tstamp_cpu, &idx); + /* Do not update the element for nested locks */ + if (pelem && pelem->lock) + pelem = NULL; + return pelem; + } + + pid = bpf_get_current_pid_tgid(); + pelem = bpf_map_lookup_elem(&tstamp, &pid); + /* Do not update the element for nested locks */ + if (pelem && pelem->lock) + return NULL; + + if (pelem == NULL) { + struct tstamp_data zero = {}; + + if (bpf_map_update_elem(&tstamp, &pid, &zero, BPF_NOEXIST) < 0) { + __sync_fetch_and_add(&task_fail, 1); + return NULL; + } + + pelem = bpf_map_lookup_elem(&tstamp, &pid); + if (pelem == NULL) { + __sync_fetch_and_add(&task_fail, 1); + return NULL; + } + } + return pelem; +} + SEC("tp_btf/contention_begin") int contention_begin(u64 *ctx) { - __u32 pid; struct tstamp_data *pelem; if (!enabled || !can_record(ctx)) return 0; - pid = bpf_get_current_pid_tgid(); - pelem = bpf_map_lookup_elem(&tstamp, &pid); - if (pelem && pelem->lock) + pelem = get_tstamp_elem(ctx[1]); + if (pelem == NULL) return 0; - if (pelem == NULL) { - struct tstamp_data zero = {}; - - bpf_map_update_elem(&tstamp, &pid, &zero, BPF_ANY); - pelem = bpf_map_lookup_elem(&tstamp, &pid); - if (pelem == NULL) { - __sync_fetch_and_add(&task_fail, 1); - return 0; - } - } - pelem->timestamp = bpf_ktime_get_ns(); pelem->lock = (__u64)ctx[0]; pelem->flags = (__u32)ctx[1]; @@ -330,23 +408,42 @@ int contention_begin(u64 *ctx) SEC("tp_btf/contention_end") int contention_end(u64 *ctx) { - __u32 pid; + __u32 pid = 0, idx = 0; struct tstamp_data *pelem; struct contention_key key = {}; struct contention_data *data; __u64 duration; + bool need_delete = false; if (!enabled) return 0; - pid = bpf_get_current_pid_tgid(); - pelem = bpf_map_lookup_elem(&tstamp, &pid); - if (!pelem || pelem->lock != ctx[0]) - return 0; + /* + * For spinlock and rwlock, it needs to get the timestamp for the + * per-cpu map. However, contention_end does not have the flags + * so it cannot know whether it reads percpu or hash map. + * + * Try per-cpu map first and check if there's active contention. + * If it is, do not read hash map because it cannot go to sleeping + * locks before releasing the spinning locks. + */ + pelem = bpf_map_lookup_elem(&tstamp_cpu, &idx); + if (pelem && pelem->lock) { + if (pelem->lock != ctx[0]) + return 0; + } else { + pid = bpf_get_current_pid_tgid(); + pelem = bpf_map_lookup_elem(&tstamp, &pid); + if (!pelem || pelem->lock != ctx[0]) + return 0; + need_delete = true; + } duration = bpf_ktime_get_ns() - pelem->timestamp; if ((__s64)duration < 0) { - bpf_map_delete_elem(&tstamp, &pid); + pelem->lock = 0; + if (need_delete) + bpf_map_delete_elem(&tstamp, &pid); __sync_fetch_and_add(&time_fail, 1); return 0; } @@ -358,16 +455,22 @@ int contention_end(u64 *ctx) case LOCK_AGGR_TASK: if (lock_owner) key.pid = pelem->flags; - else + else { + if (!need_delete) + pid = bpf_get_current_pid_tgid(); key.pid = pid; + } if (needs_callstack) key.stack_id = pelem->stack_id; break; case LOCK_AGGR_ADDR: - key.lock_addr = pelem->lock; + key.lock_addr_or_cgroup = pelem->lock; if (needs_callstack) key.stack_id = pelem->stack_id; break; + case LOCK_AGGR_CGROUP: + key.lock_addr_or_cgroup = get_current_cgroup_id(); + break; default: /* should not happen */ return 0; @@ -376,7 +479,9 @@ int contention_end(u64 *ctx) data = bpf_map_lookup_elem(&lock_stat, &key); if (!data) { if (data_map_full) { - bpf_map_delete_elem(&tstamp, &pid); + pelem->lock = 0; + if (need_delete) + bpf_map_delete_elem(&tstamp, &pid); __sync_fetch_and_add(&data_fail, 1); return 0; } @@ -399,7 +504,9 @@ int contention_end(u64 *ctx) data_map_full = 1; __sync_fetch_and_add(&data_fail, 1); } - bpf_map_delete_elem(&tstamp, &pid); + pelem->lock = 0; + if (need_delete) + bpf_map_delete_elem(&tstamp, &pid); return 0; } @@ -412,7 +519,9 @@ int contention_end(u64 *ctx) if (data->min_time > duration) data->min_time = duration; - bpf_map_delete_elem(&tstamp, &pid); + pelem->lock = 0; + if (need_delete) + bpf_map_delete_elem(&tstamp, &pid); return 0; } diff --git a/tools/perf/util/bpf_skel/lock_data.h b/tools/perf/util/bpf_skel/lock_data.h index 260062a9f2ab..08482daf61be 100644 --- a/tools/perf/util/bpf_skel/lock_data.h +++ b/tools/perf/util/bpf_skel/lock_data.h @@ -6,7 +6,7 @@ struct contention_key { u32 stack_id; u32 pid; - u64 lock_addr; + u64 lock_addr_or_cgroup; }; #define TASK_COMM_LEN 16 @@ -39,6 +39,7 @@ enum lock_aggr_mode { LOCK_AGGR_ADDR = 0, LOCK_AGGR_TASK, LOCK_AGGR_CALLER, + LOCK_AGGR_CGROUP, }; enum lock_class_sym { diff --git a/tools/perf/util/bpf_skel/vmlinux/.gitignore b/tools/perf/util/bpf_skel/vmlinux/.gitignore new file mode 100644 index 000000000000..49502c04183a --- /dev/null +++ b/tools/perf/util/bpf_skel/vmlinux/.gitignore @@ -0,0 +1 @@ +!vmlinux.h diff --git a/tools/perf/util/branch.c b/tools/perf/util/branch.c index 378f16a24751..ab760e267d41 100644 --- a/tools/perf/util/branch.c +++ b/tools/perf/util/branch.c @@ -109,7 +109,7 @@ const char *get_branch_type(struct branch_entry *e) return branch_type_name(e->flags.type); } -void branch_type_stat_display(FILE *fp, struct branch_type_stat *st) +void branch_type_stat_display(FILE *fp, const struct branch_type_stat *st) { u64 total = 0; int i; @@ -171,7 +171,7 @@ static int count_str_scnprintf(int idx, const char *str, char *bf, int size) return scnprintf(bf, size, "%s%s", (idx) ? " " : " (", str); } -int branch_type_str(struct branch_type_stat *st, char *bf, int size) +int branch_type_str(const struct branch_type_stat *st, char *bf, int size) { int i, j = 0, printed = 0; u64 total = 0; diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h index e41bfffe2217..87704d713ff6 100644 --- a/tools/perf/util/branch.h +++ b/tools/perf/util/branch.h @@ -86,8 +86,8 @@ void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags, const char *branch_type_name(int type); const char *branch_new_type_name(int new_type); const char *get_branch_type(struct branch_entry *e); -void branch_type_stat_display(FILE *fp, struct branch_type_stat *st); -int branch_type_str(struct branch_type_stat *st, char *bf, int bfsize); +void branch_type_stat_display(FILE *fp, const struct branch_type_stat *st); +int branch_type_str(const struct branch_type_stat *st, char *bf, int bfsize); const char *branch_spec_desc(int spec); diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index aee937d14fbb..8262f69118db 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -586,7 +586,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) call = zalloc(sizeof(*call)); if (!call) { perror("not enough memory for the code path tree"); - return -1; + return -ENOMEM; } call->ip = cursor_node->ip; call->ms = cursor_node->ms; @@ -602,7 +602,15 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) * branch_from is set with value somewhere else * to imply it's "to" of a branch. */ - call->brtype_stat.branch_to = true; + if (!call->brtype_stat) { + call->brtype_stat = zalloc(sizeof(*call->brtype_stat)); + if (!call->brtype_stat) { + perror("not enough memory for the code path branch statistics"); + free(call->brtype_stat); + return -ENOMEM; + } + } + call->brtype_stat->branch_to = true; if (cursor_node->branch_flags.predicted) call->predicted_count = 1; @@ -610,7 +618,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) if (cursor_node->branch_flags.abort) call->abort_count = 1; - branch_type_count(&call->brtype_stat, + branch_type_count(call->brtype_stat, &cursor_node->branch_flags, cursor_node->branch_from, cursor_node->ip); @@ -618,7 +626,8 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) /* * It's "from" of a branch */ - call->brtype_stat.branch_to = false; + if (call->brtype_stat && call->brtype_stat->branch_to) + call->brtype_stat->branch_to = false; call->cycles_count = cursor_node->branch_flags.cycles; call->iter_count = cursor_node->nr_loop_iter; @@ -650,8 +659,8 @@ add_child(struct callchain_node *parent, list_for_each_entry_safe(call, tmp, &new->val, list) { list_del_init(&call->list); - map__zput(call->ms.map); - maps__zput(call->ms.maps); + map_symbol__exit(&call->ms); + zfree(&call->brtype_stat); free(call); } free(new); @@ -762,7 +771,14 @@ static enum match_result match_chain(struct callchain_cursor_node *node, /* * It's "to" of a branch */ - cnode->brtype_stat.branch_to = true; + if (!cnode->brtype_stat) { + cnode->brtype_stat = zalloc(sizeof(*cnode->brtype_stat)); + if (!cnode->brtype_stat) { + perror("not enough memory for the code path branch statistics"); + return MATCH_ERROR; + } + } + cnode->brtype_stat->branch_to = true; if (node->branch_flags.predicted) cnode->predicted_count++; @@ -770,7 +786,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node, if (node->branch_flags.abort) cnode->abort_count++; - branch_type_count(&cnode->brtype_stat, + branch_type_count(cnode->brtype_stat, &node->branch_flags, node->branch_from, node->ip); @@ -778,7 +794,8 @@ static enum match_result match_chain(struct callchain_cursor_node *node, /* * It's "from" of a branch */ - cnode->brtype_stat.branch_to = false; + if (cnode->brtype_stat && cnode->brtype_stat->branch_to) + cnode->brtype_stat->branch_to = false; cnode->cycles_count += node->branch_flags.cycles; cnode->iter_count += node->nr_loop_iter; cnode->iter_cycles += node->iter_cycles; @@ -1022,10 +1039,9 @@ merge_chain_branch(struct callchain_cursor *cursor, }; callchain_cursor_append(cursor, list->ip, &ms, false, NULL, 0, 0, 0, list->srcline); list_del_init(&list->list); - map__zput(ms.map); - maps__zput(ms.maps); - map__zput(list->ms.map); - maps__zput(list->ms.maps); + map_symbol__exit(&ms); + map_symbol__exit(&list->ms); + zfree(&list->brtype_stat); free(list); } @@ -1077,8 +1093,7 @@ int callchain_cursor_append(struct callchain_cursor *cursor, } node->ip = ip; - maps__zput(node->ms.maps); - map__zput(node->ms.map); + map_symbol__exit(&node->ms); node->ms = *ms; node->ms.maps = maps__get(ms->maps); node->ms.map = map__get(ms->map); @@ -1142,7 +1157,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * if (al->map == NULL) goto out; } - if (RC_CHK_ACCESS(al->maps) == RC_CHK_ACCESS(machine__kernel_maps(machine))) { + if (RC_CHK_EQUAL(al->maps, machine__kernel_maps(machine))) { if (machine__is_host(machine)) { al->cpumode = PERF_RECORD_MISC_KERNEL; al->level = 'k'; @@ -1339,7 +1354,7 @@ static int count_float_printf(int idx, const char *str, float value, static int branch_to_str(char *bf, int bfsize, u64 branch_count, u64 predicted_count, u64 abort_count, - struct branch_type_stat *brtype_stat) + const struct branch_type_stat *brtype_stat) { int printed, i = 0; @@ -1403,7 +1418,7 @@ static int counts_str_build(char *bf, int bfsize, u64 abort_count, u64 cycles_count, u64 iter_count, u64 iter_cycles, u64 from_count, - struct branch_type_stat *brtype_stat) + const struct branch_type_stat *brtype_stat) { int printed; @@ -1430,7 +1445,7 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, u64 abort_count, u64 cycles_count, u64 iter_count, u64 iter_cycles, u64 from_count, - struct branch_type_stat *brtype_stat) + const struct branch_type_stat *brtype_stat) { char str[256]; @@ -1447,11 +1462,14 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize, int callchain_list_counts__printf_value(struct callchain_list *clist, FILE *fp, char *bf, int bfsize) { + static const struct branch_type_stat empty_brtype_stat = {}; + const struct branch_type_stat *brtype_stat; u64 branch_count, predicted_count; u64 abort_count, cycles_count; u64 iter_count, iter_cycles; u64 from_count; + brtype_stat = clist->brtype_stat ?: &empty_brtype_stat; branch_count = clist->branch_count; predicted_count = clist->predicted_count; abort_count = clist->abort_count; @@ -1463,7 +1481,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist, return callchain_counts_printf(fp, bf, bfsize, branch_count, predicted_count, abort_count, cycles_count, iter_count, iter_cycles, - from_count, &clist->brtype_stat); + from_count, brtype_stat); } static void free_callchain_node(struct callchain_node *node) @@ -1474,15 +1492,15 @@ static void free_callchain_node(struct callchain_node *node) list_for_each_entry_safe(list, tmp, &node->parent_val, list) { list_del_init(&list->list); - map__zput(list->ms.map); - maps__zput(list->ms.maps); + map_symbol__exit(&list->ms); + zfree(&list->brtype_stat); free(list); } list_for_each_entry_safe(list, tmp, &node->val, list) { list_del_init(&list->list); - map__zput(list->ms.map); - maps__zput(list->ms.maps); + map_symbol__exit(&list->ms); + zfree(&list->brtype_stat); free(list); } @@ -1567,8 +1585,8 @@ int callchain_node__make_parent_list(struct callchain_node *node) out: list_for_each_entry_safe(chain, new, &head, list) { list_del_init(&chain->list); - map__zput(chain->ms.map); - maps__zput(chain->ms.maps); + map_symbol__exit(&chain->ms); + zfree(&chain->brtype_stat); free(chain); } return -ENOMEM; @@ -1651,10 +1669,8 @@ void callchain_cursor_reset(struct callchain_cursor *cursor) cursor->nr = 0; cursor->last = &cursor->first; - for (node = cursor->first; node != NULL; node = node->next) { - map__zput(node->ms.map); - maps__zput(node->ms.maps); - } + for (node = cursor->first; node != NULL; node = node->next) + map_symbol__exit(&node->ms); } void callchain_param_setup(u64 sample_type, const char *arch) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index d2618a47deca..d5c66345ae31 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -116,22 +116,22 @@ extern struct callchain_param callchain_param; extern struct callchain_param callchain_param_default; struct callchain_list { + struct list_head list; u64 ip; struct map_symbol ms; + const char *srcline; + u64 branch_count; + u64 from_count; + u64 cycles_count; + u64 iter_count; + u64 iter_cycles; + struct branch_type_stat *brtype_stat; + u64 predicted_count; + u64 abort_count; struct /* for TUI */ { bool unfolded; bool has_children; }; - u64 branch_count; - u64 from_count; - u64 predicted_count; - u64 abort_count; - u64 cycles_count; - u64 iter_count; - u64 iter_cycles; - struct branch_type_stat brtype_stat; - const char *srcline; - struct list_head list; }; /* diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index bfb13306d82c..fcb509058499 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c @@ -48,28 +48,36 @@ static int open_cgroup(const char *name) } #ifdef HAVE_FILE_HANDLE -int read_cgroup_id(struct cgroup *cgrp) +static u64 __read_cgroup_id(const char *path) { - char path[PATH_MAX + 1]; - char mnt[PATH_MAX + 1]; struct { struct file_handle fh; uint64_t cgroup_id; } handle; int mount_id; + handle.fh.handle_bytes = sizeof(handle.cgroup_id); + if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0) + return -1ULL; + + return handle.cgroup_id; +} + +int read_cgroup_id(struct cgroup *cgrp) +{ + char path[PATH_MAX + 1]; + char mnt[PATH_MAX + 1]; + if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1, "perf_event")) return -1; scnprintf(path, PATH_MAX, "%s/%s", mnt, cgrp->name); - handle.fh.handle_bytes = sizeof(handle.cgroup_id); - if (name_to_handle_at(AT_FDCWD, path, &handle.fh, &mount_id, 0) < 0) - return -1; - - cgrp->id = handle.cgroup_id; + cgrp->id = __read_cgroup_id(path); return 0; } +#else +static inline u64 __read_cgroup_id(const char *path __maybe_unused) { return -1ULL; } #endif /* HAVE_FILE_HANDLE */ #ifndef CGROUP2_SUPER_MAGIC @@ -106,7 +114,7 @@ static struct cgroup *evlist__find_cgroup(struct evlist *evlist, const char *str return NULL; } -static struct cgroup *cgroup__new(const char *name, bool do_open) +struct cgroup *cgroup__new(const char *name, bool do_open) { struct cgroup *cgroup = zalloc(sizeof(*cgroup)); @@ -562,6 +570,11 @@ struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id, return cgrp; } +struct cgroup *__cgroup__find(struct rb_root *root, uint64_t id) +{ + return __cgroup__findnew(root, id, /*create=*/false, /*path=*/NULL); +} + struct cgroup *cgroup__find(struct perf_env *env, uint64_t id) { struct cgroup *cgrp; @@ -587,3 +600,35 @@ void perf_env__purge_cgroups(struct perf_env *env) } up_write(&env->cgroups.lock); } + +void read_all_cgroups(struct rb_root *root) +{ + char mnt[PATH_MAX]; + struct cgroup_name *cn; + int prefix_len; + + if (cgroupfs_find_mountpoint(mnt, sizeof(mnt), "perf_event")) + return; + + /* cgroup_name will have a full path, skip the root directory */ + prefix_len = strlen(mnt); + + /* collect all cgroups in the cgroup_list */ + if (nftw(mnt, add_cgroup_name, 20, 0) < 0) + return; + + list_for_each_entry(cn, &cgroup_list, list) { + const char *name; + u64 cgrp_id; + + /* cgroup_name might have a full path, skip the prefix */ + name = cn->name + prefix_len; + if (name[0] == '\0') + name = "/"; + + cgrp_id = __read_cgroup_id(cn->name); + __cgroup__findnew(root, cgrp_id, /*create=*/true, name); + } + + release_cgroup_list(); +} diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h index 12256b78608c..de8882d6e8d3 100644 --- a/tools/perf/util/cgroup.h +++ b/tools/perf/util/cgroup.h @@ -26,6 +26,7 @@ void cgroup__put(struct cgroup *cgroup); struct evlist; struct rblist; +struct cgroup *cgroup__new(const char *name, bool do_open); struct cgroup *evlist__findnew_cgroup(struct evlist *evlist, const char *name); int evlist__expand_cgroup(struct evlist *evlist, const char *cgroups, struct rblist *metric_events, bool open_cgroup); @@ -37,6 +38,7 @@ int parse_cgroups(const struct option *opt, const char *str, int unset); struct cgroup *cgroup__findnew(struct perf_env *env, uint64_t id, const char *path); struct cgroup *cgroup__find(struct perf_env *env, uint64_t id); +struct cgroup *__cgroup__find(struct rb_root *root, uint64_t id); void perf_env__purge_cgroups(struct perf_env *env); @@ -49,6 +51,9 @@ static inline int read_cgroup_id(struct cgroup *cgrp __maybe_unused) } #endif /* HAVE_FILE_HANDLE */ +/* read all cgroups in the system and save them in the rbtree */ +void read_all_cgroups(struct rb_root *root); + int cgroup_is_v2(const char *subsys); #endif /* __CGROUP_H__ */ diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 9729d006550d..a9873d14c632 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -282,23 +282,32 @@ static int cs_etm__metadata_set_trace_id(u8 trace_chan_id, u64 *cpu_metadata) return 0; } +/* + * Get a metadata index for a specific cpu from an array. + * + */ +static int get_cpu_data_idx(struct cs_etm_auxtrace *etm, int cpu) +{ + int i; + + for (i = 0; i < etm->num_cpu; i++) { + if (etm->metadata[i][CS_ETM_CPU] == (u64)cpu) { + return i; + } + } + + return -1; +} + /* * Get a metadata for a specific cpu from an array. * */ static u64 *get_cpu_data(struct cs_etm_auxtrace *etm, int cpu) { - int i; - u64 *metadata = NULL; + int idx = get_cpu_data_idx(etm, cpu); - for (i = 0; i < etm->num_cpu; i++) { - if (etm->metadata[i][CS_ETM_CPU] == (u64)cpu) { - metadata = etm->metadata[i]; - break; - } - } - - return metadata; + return (idx != -1) ? etm->metadata[idx] : NULL; } /* @@ -641,66 +650,80 @@ static void cs_etm__packet_dump(const char *pkt_string) } static void cs_etm__set_trace_param_etmv3(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, int idx, - u32 etmidr) + struct cs_etm_auxtrace *etm, int t_idx, + int m_idx, u32 etmidr) { u64 **metadata = etm->metadata; - t_params[idx].protocol = cs_etm__get_v7_protocol_version(etmidr); - t_params[idx].etmv3.reg_ctrl = metadata[idx][CS_ETM_ETMCR]; - t_params[idx].etmv3.reg_trc_id = metadata[idx][CS_ETM_ETMTRACEIDR]; + t_params[t_idx].protocol = cs_etm__get_v7_protocol_version(etmidr); + t_params[t_idx].etmv3.reg_ctrl = metadata[m_idx][CS_ETM_ETMCR]; + t_params[t_idx].etmv3.reg_trc_id = metadata[m_idx][CS_ETM_ETMTRACEIDR]; } static void cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, int idx) + struct cs_etm_auxtrace *etm, int t_idx, + int m_idx) { u64 **metadata = etm->metadata; - t_params[idx].protocol = CS_ETM_PROTO_ETMV4i; - t_params[idx].etmv4.reg_idr0 = metadata[idx][CS_ETMV4_TRCIDR0]; - t_params[idx].etmv4.reg_idr1 = metadata[idx][CS_ETMV4_TRCIDR1]; - t_params[idx].etmv4.reg_idr2 = metadata[idx][CS_ETMV4_TRCIDR2]; - t_params[idx].etmv4.reg_idr8 = metadata[idx][CS_ETMV4_TRCIDR8]; - t_params[idx].etmv4.reg_configr = metadata[idx][CS_ETMV4_TRCCONFIGR]; - t_params[idx].etmv4.reg_traceidr = metadata[idx][CS_ETMV4_TRCTRACEIDR]; + t_params[t_idx].protocol = CS_ETM_PROTO_ETMV4i; + t_params[t_idx].etmv4.reg_idr0 = metadata[m_idx][CS_ETMV4_TRCIDR0]; + t_params[t_idx].etmv4.reg_idr1 = metadata[m_idx][CS_ETMV4_TRCIDR1]; + t_params[t_idx].etmv4.reg_idr2 = metadata[m_idx][CS_ETMV4_TRCIDR2]; + t_params[t_idx].etmv4.reg_idr8 = metadata[m_idx][CS_ETMV4_TRCIDR8]; + t_params[t_idx].etmv4.reg_configr = metadata[m_idx][CS_ETMV4_TRCCONFIGR]; + t_params[t_idx].etmv4.reg_traceidr = metadata[m_idx][CS_ETMV4_TRCTRACEIDR]; } static void cs_etm__set_trace_param_ete(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, int idx) + struct cs_etm_auxtrace *etm, int t_idx, + int m_idx) { u64 **metadata = etm->metadata; - t_params[idx].protocol = CS_ETM_PROTO_ETE; - t_params[idx].ete.reg_idr0 = metadata[idx][CS_ETE_TRCIDR0]; - t_params[idx].ete.reg_idr1 = metadata[idx][CS_ETE_TRCIDR1]; - t_params[idx].ete.reg_idr2 = metadata[idx][CS_ETE_TRCIDR2]; - t_params[idx].ete.reg_idr8 = metadata[idx][CS_ETE_TRCIDR8]; - t_params[idx].ete.reg_configr = metadata[idx][CS_ETE_TRCCONFIGR]; - t_params[idx].ete.reg_traceidr = metadata[idx][CS_ETE_TRCTRACEIDR]; - t_params[idx].ete.reg_devarch = metadata[idx][CS_ETE_TRCDEVARCH]; + t_params[t_idx].protocol = CS_ETM_PROTO_ETE; + t_params[t_idx].ete.reg_idr0 = metadata[m_idx][CS_ETE_TRCIDR0]; + t_params[t_idx].ete.reg_idr1 = metadata[m_idx][CS_ETE_TRCIDR1]; + t_params[t_idx].ete.reg_idr2 = metadata[m_idx][CS_ETE_TRCIDR2]; + t_params[t_idx].ete.reg_idr8 = metadata[m_idx][CS_ETE_TRCIDR8]; + t_params[t_idx].ete.reg_configr = metadata[m_idx][CS_ETE_TRCCONFIGR]; + t_params[t_idx].ete.reg_traceidr = metadata[m_idx][CS_ETE_TRCTRACEIDR]; + t_params[t_idx].ete.reg_devarch = metadata[m_idx][CS_ETE_TRCDEVARCH]; } static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, struct cs_etm_auxtrace *etm, + bool formatted, + int sample_cpu, int decoders) { - int i; + int t_idx, m_idx; u32 etmidr; u64 architecture; - for (i = 0; i < decoders; i++) { - architecture = etm->metadata[i][CS_ETM_MAGIC]; + for (t_idx = 0; t_idx < decoders; t_idx++) { + if (formatted) + m_idx = t_idx; + else { + m_idx = get_cpu_data_idx(etm, sample_cpu); + if (m_idx == -1) { + pr_warning("CS_ETM: unknown CPU, falling back to first metadata\n"); + m_idx = 0; + } + } + + architecture = etm->metadata[m_idx][CS_ETM_MAGIC]; switch (architecture) { case __perf_cs_etmv3_magic: - etmidr = etm->metadata[i][CS_ETM_ETMIDR]; - cs_etm__set_trace_param_etmv3(t_params, etm, i, etmidr); + etmidr = etm->metadata[m_idx][CS_ETM_ETMIDR]; + cs_etm__set_trace_param_etmv3(t_params, etm, t_idx, m_idx, etmidr); break; case __perf_cs_etmv4_magic: - cs_etm__set_trace_param_etmv4(t_params, etm, i); + cs_etm__set_trace_param_etmv4(t_params, etm, t_idx, m_idx); break; case __perf_cs_ete_magic: - cs_etm__set_trace_param_ete(t_params, etm, i); + cs_etm__set_trace_param_ete(t_params, etm, t_idx, m_idx); break; default: return -EINVAL; @@ -1016,7 +1039,7 @@ out: } static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, - bool formatted) + bool formatted, int sample_cpu) { struct cs_etm_decoder_params d_params; struct cs_etm_trace_params *t_params = NULL; @@ -1041,7 +1064,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, if (!t_params) goto out_free; - if (cs_etm__init_trace_params(t_params, etm, decoders)) + if (cs_etm__init_trace_params(t_params, etm, formatted, sample_cpu, decoders)) goto out_free; /* Set decoder parameters to decode trace packets */ @@ -1081,14 +1104,15 @@ out_free: static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, struct auxtrace_queue *queue, unsigned int queue_nr, - bool formatted) + bool formatted, + int sample_cpu) { struct cs_etm_queue *etmq = queue->priv; if (list_empty(&queue->head) || etmq) return 0; - etmq = cs_etm__alloc_queue(etm, formatted); + etmq = cs_etm__alloc_queue(etm, formatted, sample_cpu); if (!etmq) return -ENOMEM; @@ -2816,7 +2840,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session, * formatted in piped mode (true). */ err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], - idx, true); + idx, true, -1); if (err) return err; @@ -3022,7 +3046,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o idx = auxtrace_event->idx; formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW); return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], - idx, formatted); + idx, formatted, sample->cpu); } /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */ diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 7cca37887917..4696267a32f0 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -242,7 +242,7 @@ struct cs_etm_packet_queue { int cs_etm__process_auxtrace_info(union perf_event *event, struct perf_session *session); -struct perf_event_attr *cs_etm_get_default_config(struct perf_pmu *pmu); +void cs_etm_get_default_config(const struct perf_pmu *pmu, struct perf_event_attr *attr); enum cs_etm_pid_fmt { CS_ETM_PIDFMT_NONE, diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index fc16299c915f..c29d8a382b19 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c @@ -17,6 +17,7 @@ #include "util.h" // rm_rf_perf_data() #include "debug.h" #include "header.h" +#include "rlimit.h" #include static void close_dir(struct perf_data_file *files, int nr) @@ -35,6 +36,7 @@ void perf_data__close_dir(struct perf_data *data) int perf_data__create_dir(struct perf_data *data, int nr) { + enum rlimit_action set_rlimit = NO_CHANGE; struct perf_data_file *files = NULL; int i, ret; @@ -54,11 +56,21 @@ int perf_data__create_dir(struct perf_data *data, int nr) goto out_err; } +retry_open: ret = open(file->path, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); if (ret < 0) { + /* + * If using parallel threads to collect data, + * perf record needs at least 6 fds per CPU. + * When we run out of them try to increase the limits. + */ + if (errno == EMFILE && rlimit__increase_nofile(&set_rlimit)) + goto retry_open; + ret = -errno; goto out_err; } + set_rlimit = NO_CHANGE; file->fd = ret; } diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c index 4a1dc21b0450..908e16813722 100644 --- a/tools/perf/util/dlfilter.c +++ b/tools/perf/util/dlfilter.c @@ -52,8 +52,10 @@ static void al_to_d_al(struct addr_location *al, struct perf_dlfilter_al *d_al) d_al->sym_end = sym->end; if (al->addr < sym->end) d_al->symoff = al->addr - sym->start; - else + else if (al->map) d_al->symoff = al->addr - map__start(al->map) - sym->start; + else + d_al->symoff = 0; d_al->sym_binding = sym->binding; } else { d_al->sym = NULL; diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index bdfead36b83a..1f629b6fb7cf 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -477,6 +477,7 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m, dso->comp = m->comp; } + dso->is_kmod = 1; dso__set_short_name(dso, strdup(m->name), true); } @@ -1338,6 +1339,7 @@ struct dso *dso__new_id(const char *name, struct dso_id *id) dso->has_srcline = 1; dso->a2l_fails = 1; dso->kernel = DSO_SPACE__USER; + dso->is_kmod = 0; dso->needs_swap = DSO_SWAP__UNSET; dso->comp = COMP_ID__NONE; RB_CLEAR_NODE(&dso->rb_node); diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index b41c9782c754..3759de8c2267 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -162,6 +162,7 @@ struct dso { char *symsrc_filename; unsigned int a2l_fails; enum dso_space_type kernel; + bool is_kmod; enum dso_swap_type needs_swap; enum dso_binary_type symtab_type; enum dso_binary_type binary_type; @@ -181,6 +182,7 @@ struct dso { u8 rel; struct build_id bid; u64 text_offset; + u64 text_end; const char *short_name; const char *long_name; u16 long_name_len; diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index a164164001fb..44140b7f596a 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -457,7 +457,7 @@ const char *perf_env__cpuid(struct perf_env *env) { int status; - if (!env || !env->cpuid) { /* Assume local operation */ + if (!env->cpuid) { /* Assume local operation */ status = perf_env__read_cpuid(env); if (status) return NULL; @@ -470,7 +470,7 @@ int perf_env__nr_pmu_mappings(struct perf_env *env) { int status; - if (!env || !env->nr_pmu_mappings) { /* Assume local operation */ + if (!env->nr_pmu_mappings) { /* Assume local operation */ status = perf_env__read_pmu_mappings(env); if (status) return 0; @@ -483,7 +483,7 @@ const char *perf_env__pmu_mappings(struct perf_env *env) { int status; - if (!env || !env->pmu_mappings) { /* Assume local operation */ + if (!env->pmu_mappings) { /* Assume local operation */ status = perf_env__read_pmu_mappings(env); if (status) return NULL; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7ef43f72098e..e36da58522ef 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -251,6 +251,9 @@ static struct evsel *evlist__dummy_event(struct evlist *evlist) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_DUMMY, .size = sizeof(attr), /* to capture ABI version */ + /* Avoid frequency mode for dummy events to avoid associated timers. */ + .freq = 0, + .sample_period = 1, }; return evsel__new_idx(&attr, evlist->core.nr_entries); @@ -277,8 +280,6 @@ struct evsel *evlist__add_aux_dummy(struct evlist *evlist, bool system_wide) evsel->core.attr.exclude_kernel = 1; evsel->core.attr.exclude_guest = 1; evsel->core.attr.exclude_hv = 1; - evsel->core.attr.freq = 0; - evsel->core.attr.sample_period = 1; evsel->core.system_wide = system_wide; evsel->no_aux_samples = true; evsel->name = strdup("dummy:u"); @@ -1694,6 +1695,24 @@ void evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_ev tracking_evsel->tracking = true; } +struct evsel *evlist__findnew_tracking_event(struct evlist *evlist, bool system_wide) +{ + struct evsel *evsel; + + evsel = evlist__get_tracking_event(evlist); + if (!evsel__is_dummy_event(evsel)) { + evsel = evlist__add_aux_dummy(evlist, system_wide); + if (!evsel) + return NULL; + + evlist__set_tracking_event(evlist, evsel); + } else if (system_wide) { + perf_evlist__go_system_wide(&evlist->core, &evsel->core); + } + + return evsel; +} + struct evsel *evlist__find_evsel_by_str(struct evlist *evlist, const char *str) { struct evsel *evsel; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 664c6bf7b3e0..98e7ddb2bd30 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -387,6 +387,7 @@ bool evlist_cpu_iterator__end(const struct evlist_cpu_iterator *evlist_cpu_itr); struct evsel *evlist__get_tracking_event(struct evlist *evlist); void evlist__set_tracking_event(struct evlist *evlist, struct evsel *tracking_evsel); +struct evsel *evlist__findnew_tracking_event(struct evlist *evlist, bool system_wide); struct evsel *evlist__find_evsel_by_str(struct evlist *evlist, const char *str); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a8a5ff87cc1f..72a5dfc38d38 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -49,6 +49,7 @@ #include "off_cpu.h" #include "pmu.h" #include "pmus.h" +#include "rlimit.h" #include "../perf-sys.h" #include "util/parse-branch-options.h" #include "util/bpf-filter.h" @@ -1989,33 +1990,6 @@ bool evsel__detect_missing_features(struct evsel *evsel) } } -bool evsel__increase_rlimit(enum rlimit_action *set_rlimit) -{ - int old_errno; - struct rlimit l; - - if (*set_rlimit < INCREASED_MAX) { - old_errno = errno; - - if (getrlimit(RLIMIT_NOFILE, &l) == 0) { - if (*set_rlimit == NO_CHANGE) { - l.rlim_cur = l.rlim_max; - } else { - l.rlim_cur = l.rlim_max + 1000; - l.rlim_max = l.rlim_cur; - } - if (setrlimit(RLIMIT_NOFILE, &l) == 0) { - (*set_rlimit) += 1; - errno = old_errno; - return true; - } - } - errno = old_errno; - } - - return false; -} - static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads, int start_cpu_map_idx, int end_cpu_map_idx) @@ -2143,7 +2117,7 @@ try_fallback: * perf stat needs between 5 and 22 fds per CPU. When we run out * of them try to increase the limits. */ - if (err == -EMFILE && evsel__increase_rlimit(&set_rlimit)) + if (err == -EMFILE && rlimit__increase_nofile(&set_rlimit)) goto retry_open; if (err != -EINVAL || idx > 0 || thread > 0) @@ -2766,6 +2740,11 @@ struct tep_format_field *evsel__field(struct evsel *evsel, const char *name) return tep_find_field(evsel->tp_format, name); } +struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *name) +{ + return tep_find_common_field(evsel->tp_format, name); +} + void *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name) { struct tep_format_field *field = evsel__field(evsel, name); @@ -2831,6 +2810,14 @@ u64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *n return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; } + +u64 evsel__intval_common(struct evsel *evsel, struct perf_sample *sample, const char *name) +{ + struct tep_format_field *field = evsel__common_field(evsel, name); + + return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; +} + #endif bool evsel__fallback(struct evsel *evsel, int err, char *msg, size_t msgsize) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 848534ec74fa..d791316a1792 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -330,9 +330,6 @@ int evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus, struct perf_thread_map *threads); bool evsel__detect_missing_features(struct evsel *evsel); -enum rlimit_action { NO_CHANGE, SET_TO_MAX, INCREASED_MAX }; -bool evsel__increase_rlimit(enum rlimit_action *set_rlimit); - bool evsel__precise_ip_fallback(struct evsel *evsel); struct perf_sample; @@ -340,6 +337,7 @@ struct perf_sample; #ifdef HAVE_LIBTRACEEVENT void *evsel__rawptr(struct evsel *evsel, struct perf_sample *sample, const char *name); u64 evsel__intval(struct evsel *evsel, struct perf_sample *sample, const char *name); +u64 evsel__intval_common(struct evsel *evsel, struct perf_sample *sample, const char *name); static inline char *evsel__strval(struct evsel *evsel, struct perf_sample *sample, const char *name) { @@ -352,6 +350,7 @@ struct tep_format_field; u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap); struct tep_format_field *evsel__field(struct evsel *evsel, const char *name); +struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *name); static inline bool __evsel__match(const struct evsel *evsel, u32 type, u64 config) { diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 4488f306de78..7be23b3ac082 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -509,7 +509,7 @@ double expr__strcmp_cpuid_str(const struct expr_parse_ctx *ctx __maybe_unused, bool compute_ids __maybe_unused, const char *test_id) { double ret; - struct perf_pmu *pmu = pmu__find_core_pmu(); + struct perf_pmu *pmu = perf_pmus__find_core_pmu(); char *cpuid = perf_pmu__getcpuid(pmu); if (!cpuid) diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 6c93b358cc2d..e364790babb5 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -1,6 +1,8 @@ /* Simple expression parser */ %{ +#ifndef NDEBUG #define YYDEBUG 1 +#endif #include #include #include diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d812e1e371a7..e86b9439ffee 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2573,7 +2573,7 @@ error: static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) { u32 nr, i; - char *str; + char *str = NULL; struct strbuf sb; int cpu_nr = ff->ph->env.nr_cpus_avail; u64 size = 0; @@ -2601,7 +2601,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) if (strbuf_add(&sb, str, strlen(str) + 1) < 0) goto error; size += string_size(str); - free(str); + zfree(&str); } ph->env.sibling_cores = strbuf_detach(&sb, NULL); @@ -2620,7 +2620,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) if (strbuf_add(&sb, str, strlen(str) + 1) < 0) goto error; size += string_size(str); - free(str); + zfree(&str); } ph->env.sibling_threads = strbuf_detach(&sb, NULL); @@ -2684,7 +2684,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) if (strbuf_add(&sb, str, strlen(str) + 1) < 0) goto error; size += string_size(str); - free(str); + zfree(&str); } ph->env.sibling_dies = strbuf_detach(&sb, NULL); @@ -2699,6 +2699,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) error: strbuf_release(&sb); + zfree(&str); free_cpu: zfree(&ph->env.cpu); return -1; @@ -2736,10 +2737,9 @@ static int process_numa_topology(struct feat_fd *ff, void *data __maybe_unused) goto error; n->map = perf_cpu_map__new(str); + free(str); if (!n->map) goto error; - - free(str); } ff->ph->env.nr_numa_nodes = nr; ff->ph->env.numa_nodes = nodes; @@ -2913,10 +2913,10 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused) return -1; for (i = 0; i < cnt; i++) { - struct cpu_cache_level c; + struct cpu_cache_level *c = &caches[i]; #define _R(v) \ - if (do_read_u32(ff, &c.v))\ + if (do_read_u32(ff, &c->v)) \ goto out_free_caches; \ _R(level) @@ -2926,22 +2926,25 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused) #undef _R #define _R(v) \ - c.v = do_read_string(ff); \ - if (!c.v) \ - goto out_free_caches; + c->v = do_read_string(ff); \ + if (!c->v) \ + goto out_free_caches; \ _R(type) _R(size) _R(map) #undef _R - - caches[i] = c; } ff->ph->env.caches = caches; ff->ph->env.caches_cnt = cnt; return 0; out_free_caches: + for (i = 0; i < cnt; i++) { + free(caches[i].type); + free(caches[i].size); + free(caches[i].map); + } free(caches); return -1; } @@ -3585,18 +3588,16 @@ static int perf_header__adds_write(struct perf_header *header, struct feat_copier *fc) { int nr_sections; - struct feat_fd ff; + struct feat_fd ff = { + .fd = fd, + .ph = header, + }; struct perf_file_section *feat_sec, *p; int sec_size; u64 sec_start; int feat; int err; - ff = (struct feat_fd){ - .fd = fd, - .ph = header, - }; - nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS); if (!nr_sections) return 0; @@ -3623,6 +3624,7 @@ static int perf_header__adds_write(struct perf_header *header, err = do_write(&ff, feat_sec, sec_size); if (err < 0) pr_debug("failed to write feature section\n"); + free(ff.buf); /* TODO: added to silence clang-tidy. */ free(feat_sec); return err; } @@ -3630,11 +3632,11 @@ static int perf_header__adds_write(struct perf_header *header, int perf_header__write_pipe(int fd) { struct perf_pipe_file_header f_header; - struct feat_fd ff; + struct feat_fd ff = { + .fd = fd, + }; int err; - ff = (struct feat_fd){ .fd = fd }; - f_header = (struct perf_pipe_file_header){ .magic = PERF_MAGIC, .size = sizeof(f_header), @@ -3645,7 +3647,7 @@ int perf_header__write_pipe(int fd) pr_debug("failed to write perf pipe header\n"); return err; } - + free(ff.buf); return 0; } @@ -3658,11 +3660,12 @@ static int perf_session__do_write_header(struct perf_session *session, struct perf_file_attr f_attr; struct perf_header *header = &session->header; struct evsel *evsel; - struct feat_fd ff; + struct feat_fd ff = { + .fd = fd, + }; u64 attr_offset; int err; - ff = (struct feat_fd){ .fd = fd}; lseek(fd, sizeof(f_header), SEEK_SET); evlist__for_each_entry(session->evlist, evsel) { @@ -3670,6 +3673,7 @@ static int perf_session__do_write_header(struct perf_session *session, err = do_write(&ff, evsel->core.id, evsel->core.ids * sizeof(u64)); if (err < 0) { pr_debug("failed to write perf header\n"); + free(ff.buf); return err; } } @@ -3695,6 +3699,7 @@ static int perf_session__do_write_header(struct perf_session *session, err = do_write(&ff, &f_attr, sizeof(f_attr)); if (err < 0) { pr_debug("failed to write perf header attribute\n"); + free(ff.buf); return err; } } @@ -3705,8 +3710,10 @@ static int perf_session__do_write_header(struct perf_session *session, if (at_exit) { err = perf_header__adds_write(header, evlist, fd, fc); - if (err < 0) + if (err < 0) { + free(ff.buf); return err; + } } f_header = (struct perf_file_header){ @@ -3728,6 +3735,7 @@ static int perf_session__do_write_header(struct perf_session *session, lseek(fd, 0, SEEK_SET); err = do_write(&ff, &f_header, sizeof(f_header)); + free(ff.buf); if (err < 0) { pr_debug("failed to write perf header\n"); return err; diff --git a/tools/perf/util/hisi-ptt.c b/tools/perf/util/hisi-ptt.c index 45b614bb73bf..43bd1ca62d58 100644 --- a/tools/perf/util/hisi-ptt.c +++ b/tools/perf/util/hisi-ptt.c @@ -108,8 +108,10 @@ static int hisi_ptt_process_auxtrace_event(struct perf_session *session, data_offset = 0; } else { data_offset = lseek(fd, 0, SEEK_CUR); - if (data_offset == -1) + if (data_offset == -1) { + free(data); return -errno; + } } err = readn(fd, data, size); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 3dc8a4968beb..0888b7163b7c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -515,17 +515,16 @@ err_rawdata: err_infos: if (he->branch_info) { - map__put(he->branch_info->from.ms.map); - map__put(he->branch_info->to.ms.map); + map_symbol__exit(&he->branch_info->from.ms); + map_symbol__exit(&he->branch_info->to.ms); zfree(&he->branch_info); } if (he->mem_info) { - map__put(he->mem_info->iaddr.ms.map); - map__put(he->mem_info->daddr.ms.map); + map_symbol__exit(&he->mem_info->iaddr.ms); + map_symbol__exit(&he->mem_info->daddr.ms); } err: - maps__zput(he->ms.maps); - map__zput(he->ms.map); + map_symbol__exit(&he->ms); zfree(&he->stat_acc); return -ENOMEM; } @@ -1317,20 +1316,19 @@ void hist_entry__delete(struct hist_entry *he) struct hist_entry_ops *ops = he->ops; thread__zput(he->thread); - maps__zput(he->ms.maps); - map__zput(he->ms.map); + map_symbol__exit(&he->ms); if (he->branch_info) { - map__zput(he->branch_info->from.ms.map); - map__zput(he->branch_info->to.ms.map); + map_symbol__exit(&he->branch_info->from.ms); + map_symbol__exit(&he->branch_info->to.ms); zfree_srcline(&he->branch_info->srcline_from); zfree_srcline(&he->branch_info->srcline_to); zfree(&he->branch_info); } if (he->mem_info) { - map__zput(he->mem_info->iaddr.ms.map); - map__zput(he->mem_info->daddr.ms.map); + map_symbol__exit(&he->mem_info->iaddr.ms); + map_symbol__exit(&he->mem_info->daddr.ms); mem_info__zput(he->mem_info); } @@ -2142,7 +2140,7 @@ static bool hists__filter_entry_by_thread(struct hists *hists, struct hist_entry *he) { if (hists->thread_filter != NULL && - RC_CHK_ACCESS(he->thread) != RC_CHK_ACCESS(hists->thread_filter)) { + !RC_CHK_EQUAL(he->thread, hists->thread_filter)) { he->filtered |= (1 << HIST_FILTER__THREAD); return true; } @@ -2676,8 +2674,6 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, /* If we have branch cycles always annotate them. */ if (bs && bs->nr && entries[0].flags.cycles) { - int i; - bi = sample__resolve_bstack(sample, al); if (bi) { struct addr_map_symbol *prev = NULL; @@ -2692,7 +2688,7 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, * Note that perf stores branches reversed from * program order! */ - for (i = bs->nr - 1; i >= 0; i--) { + for (int i = bs->nr - 1; i >= 0; i--) { addr_map_symbol__account_cycles(&bi[i].from, nonany_branch_mode ? NULL : prev, bi[i].flags.cycles); @@ -2701,6 +2697,10 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, if (total_cycles) *total_cycles += bi[i].flags.cycles; } + for (unsigned int i = 0; i < bs->nr; i++) { + map_symbol__exit(&bi[i].to.ms); + map_symbol__exit(&bi[i].from.ms); + } free(bi); } } diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c index af9710622a1f..bccb988a7a44 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include "intel-pt-pkt-decoder.h" @@ -17,17 +19,11 @@ #define BIT63 ((uint64_t)1 << 63) #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define le16_to_cpu bswap_16 -#define le32_to_cpu bswap_32 -#define le64_to_cpu bswap_64 #define memcpy_le64(d, s, n) do { \ memcpy((d), (s), (n)); \ *(d) = le64_to_cpu(*(d)); \ } while (0) #else -#define le16_to_cpu -#define le32_to_cpu -#define le64_to_cpu #define memcpy_le64 memcpy #endif @@ -83,7 +79,7 @@ static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len, if (len < 8) return INTEL_PT_NEED_MORE_BYTES; - payload = le64_to_cpu(*(uint64_t *)buf); + payload = get_unaligned_le64(buf); for (count = 47; count; count--) { if (payload & BIT63) @@ -124,26 +120,21 @@ static int intel_pt_get_cbr(const unsigned char *buf, size_t len, if (len < 4) return INTEL_PT_NEED_MORE_BYTES; packet->type = INTEL_PT_CBR; - packet->payload = le16_to_cpu(*(uint16_t *)(buf + 2)); + packet->payload = get_unaligned_le16(buf + 2); return 4; } static int intel_pt_get_vmcs(const unsigned char *buf, size_t len, struct intel_pt_pkt *packet) { - unsigned int count = (52 - 5) >> 3; - - if (count < 1 || count > 7) - return INTEL_PT_BAD_PACKET; - - if (len < count + 2) + if (len < 7) return INTEL_PT_NEED_MORE_BYTES; packet->type = INTEL_PT_VMCS; - packet->count = count; - memcpy_le64(&packet->payload, buf + 2, count); + packet->count = 5; + memcpy_le64(&packet->payload, buf + 2, 5); - return count + 2; + return 7; } static int intel_pt_get_ovf(struct intel_pt_pkt *packet) @@ -199,7 +190,7 @@ static int intel_pt_get_mnt(const unsigned char *buf, size_t len, if (len < 11) return INTEL_PT_NEED_MORE_BYTES; packet->type = INTEL_PT_MNT; - memcpy_le64(&packet->payload, buf + 3, 8); + packet->payload = get_unaligned_le64(buf + 3); return 11; } @@ -228,12 +219,12 @@ static int intel_pt_get_ptwrite(const unsigned char *buf, size_t len, case 0: if (len < 6) return INTEL_PT_NEED_MORE_BYTES; - packet->payload = le32_to_cpu(*(uint32_t *)(buf + 2)); + packet->payload = get_unaligned_le32(buf + 2); return 6; case 1: if (len < 10) return INTEL_PT_NEED_MORE_BYTES; - packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2)); + packet->payload = get_unaligned_le64(buf + 2); return 10; default: return INTEL_PT_BAD_PACKET; @@ -258,7 +249,7 @@ static int intel_pt_get_mwait(const unsigned char *buf, size_t len, if (len < 10) return INTEL_PT_NEED_MORE_BYTES; packet->type = INTEL_PT_MWAIT; - packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2)); + packet->payload = get_unaligned_le64(buf + 2); return 10; } @@ -311,7 +302,7 @@ static int intel_pt_get_bip_8(const unsigned char *buf, size_t len, return INTEL_PT_NEED_MORE_BYTES; packet->type = INTEL_PT_BIP; packet->count = buf[0] >> 3; - memcpy_le64(&packet->payload, buf + 1, 8); + packet->payload = get_unaligned_le64(buf + 1); return 9; } @@ -350,7 +341,7 @@ static int intel_pt_get_evd(const unsigned char *buf, size_t len, packet->type = INTEL_PT_EVD; packet->count = buf[2] & 0x3f; packet->payload = buf[3]; - memcpy_le64(&packet->payload, buf + 3, 8); + packet->payload = get_unaligned_le64(buf + 3); return 11; } @@ -465,13 +456,13 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, if (len < 3) return INTEL_PT_NEED_MORE_BYTES; ip_len = 2; - packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); + packet->payload = get_unaligned_le16(buf + 1); break; case 2: if (len < 5) return INTEL_PT_NEED_MORE_BYTES; ip_len = 4; - packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); + packet->payload = get_unaligned_le32(buf + 1); break; case 3: case 4: @@ -484,7 +475,7 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, if (len < 9) return INTEL_PT_NEED_MORE_BYTES; ip_len = 8; - packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1)); + packet->payload = get_unaligned_le64(buf + 1); break; default: return INTEL_PT_BAD_PACKET; diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index dbf0bc71a63b..f38893e0b036 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -1512,9 +1512,11 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq) } else if (ptq->state->flags & INTEL_PT_ASYNC) { if (!ptq->state->to_ip) ptq->flags = PERF_IP_FLAG_BRANCH | + PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_TRACE_END; else if (ptq->state->from_nr && !ptq->state->to_nr) ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | + PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_VMEXIT; else ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h index c7d6068e3a6b..18fd0be52e6c 100644 --- a/tools/perf/util/intel-pt.h +++ b/tools/perf/util/intel-pt.h @@ -42,6 +42,7 @@ struct auxtrace_record *intel_pt_recording_init(int *err); int intel_pt_process_auxtrace_info(union perf_event *event, struct perf_session *session); -struct perf_event_attr *intel_pt_pmu_default_config(struct perf_pmu *pmu); +void intel_pt_pmu_default_config(const struct perf_pmu *intel_pt_pmu, + struct perf_event_attr *attr); #endif diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 6b2b96c16ccd..1f657ef8975f 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -675,6 +675,7 @@ jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr) jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size; jd->unwinding_size = jr->unwinding.unwinding_size; jd->unwinding_mapped_size = jr->unwinding.mapped_size; + free(jd->unwinding_data); jd->unwinding_data = unwinding_data; return 0; diff --git a/tools/perf/util/kwork.h b/tools/perf/util/kwork.h index 53b7327550b8..76fe2a821bcf 100644 --- a/tools/perf/util/kwork.h +++ b/tools/perf/util/kwork.h @@ -16,6 +16,7 @@ enum kwork_class_type { KWORK_CLASS_IRQ, KWORK_CLASS_SOFTIRQ, KWORK_CLASS_WORKQUEUE, + KWORK_CLASS_SCHED, KWORK_CLASS_MAX, }; @@ -23,6 +24,7 @@ enum kwork_report_type { KWORK_REPORT_RUNTIME, KWORK_REPORT_LATENCY, KWORK_REPORT_TIMEHIST, + KWORK_REPORT_TOP, }; enum kwork_trace_type { @@ -91,6 +93,7 @@ struct kwork_atom_page { DECLARE_BITMAP(bitmap, NR_ATOM_PER_PAGE); }; +struct perf_kwork; struct kwork_class; struct kwork_work { /* @@ -127,6 +130,13 @@ struct kwork_work { u64 max_latency_start; u64 max_latency_end; u64 total_latency; + + /* + * top report + */ + u32 cpu_usage; + u32 tgid; + bool is_kthread; }; struct kwork_class { @@ -142,8 +152,10 @@ struct kwork_class { int (*class_init)(struct kwork_class *class, struct perf_session *session); - void (*work_init)(struct kwork_class *class, + void (*work_init)(struct perf_kwork *kwork, + struct kwork_class *class, struct kwork_work *work, + enum kwork_trace_type src_type, struct evsel *evsel, struct perf_sample *sample, struct machine *machine); @@ -152,7 +164,6 @@ struct kwork_class { char *buf, int len); }; -struct perf_kwork; struct trace_kwork_handler { int (*raise_event)(struct perf_kwork *kwork, struct kwork_class *class, struct evsel *evsel, @@ -165,6 +176,23 @@ struct trace_kwork_handler { int (*exit_event)(struct perf_kwork *kwork, struct kwork_class *class, struct evsel *evsel, struct perf_sample *sample, struct machine *machine); + + int (*sched_switch_event)(struct perf_kwork *kwork, + struct kwork_class *class, struct evsel *evsel, + struct perf_sample *sample, struct machine *machine); +}; + +struct __top_cpus_runtime { + u64 load; + u64 idle; + u64 irq; + u64 softirq; + u64 total; +}; + +struct kwork_top_stat { + DECLARE_BITMAP(all_cpus_bitmap, MAX_NR_CPUS); + struct __top_cpus_runtime *cpus_runtime; }; struct perf_kwork { @@ -218,6 +246,11 @@ struct perf_kwork { u64 all_runtime; u64 all_count; u64 nr_skipped_events[KWORK_TRACE_MAX + 1]; + + /* + * perf kwork top data + */ + struct kwork_top_stat top_stat; }; struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork, @@ -233,6 +266,13 @@ void perf_kwork__report_cleanup_bpf(void); void perf_kwork__trace_start(void); void perf_kwork__trace_finish(void); +int perf_kwork__top_prepare_bpf(struct perf_kwork *kwork); +int perf_kwork__top_read_bpf(struct perf_kwork *kwork); +void perf_kwork__top_cleanup_bpf(void); + +void perf_kwork__top_start(void); +void perf_kwork__top_finish(void); + #else /* !HAVE_BPF_SKEL */ static inline int @@ -252,6 +292,23 @@ static inline void perf_kwork__report_cleanup_bpf(void) {} static inline void perf_kwork__trace_start(void) {} static inline void perf_kwork__trace_finish(void) {} +static inline int +perf_kwork__top_prepare_bpf(struct perf_kwork *kwork __maybe_unused) +{ + return -1; +} + +static inline int +perf_kwork__top_read_bpf(struct perf_kwork *kwork __maybe_unused) +{ + return -1; +} + +static inline void perf_kwork__top_cleanup_bpf(void) {} + +static inline void perf_kwork__top_start(void) {} +static inline void perf_kwork__top_finish(void) {} + #endif /* HAVE_BPF_SKEL */ #endif /* PERF_UTIL_KWORK_H */ diff --git a/tools/perf/util/lock-contention.h b/tools/perf/util/lock-contention.h index fa16532c971c..1a7248ff3889 100644 --- a/tools/perf/util/lock-contention.h +++ b/tools/perf/util/lock-contention.h @@ -9,9 +9,11 @@ struct lock_filter { int nr_types; int nr_addrs; int nr_syms; + int nr_cgrps; unsigned int *types; unsigned long *addrs; char **syms; + u64 *cgrps; }; struct lock_stat { @@ -136,6 +138,7 @@ struct lock_contention { struct hlist_head *result; struct lock_filter *filters; struct lock_contention_fails fails; + struct rb_root cgroups; unsigned long map_nr_entries; int max_stack; int stack_skip; @@ -151,7 +154,7 @@ int lock_contention_prepare(struct lock_contention *con); int lock_contention_start(void); int lock_contention_stop(void); int lock_contention_read(struct lock_contention *con); -int lock_contention_finish(void); +int lock_contention_finish(struct lock_contention *con); #else /* !HAVE_BPF_SKEL */ @@ -162,7 +165,10 @@ static inline int lock_contention_prepare(struct lock_contention *con __maybe_un static inline int lock_contention_start(void) { return 0; } static inline int lock_contention_stop(void) { return 0; } -static inline int lock_contention_finish(void) { return 0; } +static inline int lock_contention_finish(struct lock_contention *con __maybe_unused) +{ + return 0; +} static inline int lock_contention_read(struct lock_contention *con __maybe_unused) { diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 88f31b3a63ac..90c750150b19 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -67,7 +67,6 @@ static void machine__threads_init(struct machine *machine) threads->entries = RB_ROOT_CACHED; init_rwsem(&threads->lock); threads->nr = 0; - INIT_LIST_HEAD(&threads->dead); threads->last_match = NULL; } } @@ -969,7 +968,7 @@ static int machine__process_ksymbol_unregister(struct machine *machine, if (!map) return 0; - if (RC_CHK_ACCESS(map) != RC_CHK_ACCESS(machine->vmlinux_map)) + if (!RC_CHK_EQUAL(map, machine->vmlinux_map)) maps__remove(machine__kernel_maps(machine), map); else { struct dso *dso = map__dso(map); @@ -2058,7 +2057,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread_rb_n if (!nd) nd = thread_rb_node__find(th, &threads->entries.rb_root); - if (threads->last_match && RC_CHK_ACCESS(threads->last_match) == RC_CHK_ACCESS(th)) + if (threads->last_match && RC_CHK_EQUAL(threads->last_match, th)) threads__set_last_match(threads, NULL); if (lock) @@ -2213,9 +2212,7 @@ int machine__process_event(struct machine *machine, union perf_event *event, static bool symbol__match_regex(struct symbol *sym, regex_t *regex) { - if (!regexec(regex, sym->name, 0, NULL, 0)) - return true; - return false; + return regexec(regex, sym->name, 0, NULL, 0) == 0; } static void ip__resolve_ams(struct thread *thread, @@ -2392,8 +2389,7 @@ static int add_callchain_ip(struct thread *thread, iter_cycles, branch_from, srcline); out: addr_location__exit(&al); - maps__put(ms.maps); - map__put(ms.map); + map_symbol__exit(&ms); return err; } @@ -2624,16 +2620,18 @@ static int lbr_callchain_add_lbr_ip(struct thread *thread, save_lbr_cursor_node(thread, cursor, i); } - /* Add LBR ip from first entries.to */ - ip = entries[0].to; - flags = &entries[0].flags; - *branch_from = entries[0].from; - err = add_callchain_ip(thread, cursor, parent, - root_al, &cpumode, ip, - true, flags, NULL, - *branch_from); - if (err) - return err; + if (lbr_nr > 0) { + /* Add LBR ip from first entries.to */ + ip = entries[0].to; + flags = &entries[0].flags; + *branch_from = entries[0].from; + err = add_callchain_ip(thread, cursor, parent, + root_al, &cpumode, ip, + true, flags, NULL, + *branch_from); + if (err) + return err; + } return 0; } @@ -3117,8 +3115,7 @@ static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms if (ret != 0) return ret; } - map__put(ilist_ms.map); - maps__put(ilist_ms.maps); + map_symbol__exit(&ilist_ms); return ret; } diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index d034ecaf89c1..1279acda6a8a 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -35,7 +35,6 @@ struct threads { struct rb_root_cached entries; struct rw_semaphore lock; unsigned int nr; - struct list_head dead; struct thread *last_match; }; diff --git a/tools/perf/util/map_symbol.c b/tools/perf/util/map_symbol.c new file mode 100644 index 000000000000..bef5079f2403 --- /dev/null +++ b/tools/perf/util/map_symbol.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "map_symbol.h" +#include "maps.h" +#include "map.h" + +void map_symbol__exit(struct map_symbol *ms) +{ + maps__zput(ms->maps); + map__zput(ms->map); +} + +void addr_map_symbol__exit(struct addr_map_symbol *ams) +{ + map_symbol__exit(&ams->ms); +} diff --git a/tools/perf/util/map_symbol.h b/tools/perf/util/map_symbol.h index e08817b0c30f..72d5ed938ed6 100644 --- a/tools/perf/util/map_symbol.h +++ b/tools/perf/util/map_symbol.h @@ -22,4 +22,8 @@ struct addr_map_symbol { u64 phys_addr; u64 data_page_size; }; + +void map_symbol__exit(struct map_symbol *ms); +void addr_map_symbol__exit(struct addr_map_symbol *ams); + #endif // __PERF_MAP_SYMBOL diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 39ffe8ceb380..954b235e12e5 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -185,7 +185,6 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, { int i = *argv_nr, k = 0; struct perf_mem_event *e; - struct perf_pmu *pmu; for (int j = 0; j < PERF_MEM_EVENTS__MAX; j++) { e = perf_mem_events__ptr(j); @@ -202,6 +201,8 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, rec_argv[i++] = "-e"; rec_argv[i++] = perf_mem_events__name(j, NULL); } else { + struct perf_pmu *pmu = NULL; + if (!e->supported) { perf_mem_events__print_unsupport_hybrid(e, j); return -1; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 6231044a491e..0484736d9fe4 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -498,7 +498,7 @@ static int metricgroup__sys_event_iter(const struct pmu_metric *pm, while ((pmu = perf_pmus__scan(pmu))) { - if (!pmu->id || strcmp(pmu->id, pm->compat)) + if (!pmu->id || !pmu_uncore_identifier_match(pm->compat, pmu->id)) continue; return d->fn(pm, table, d->data); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 65608a3cba81..aa2f5c6fc7fc 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -34,8 +34,9 @@ #ifdef PARSER_DEBUG extern int parse_events_debug; #endif -static int get_config_terms(struct list_head *head_config, - struct list_head *head_terms __maybe_unused); +static int get_config_terms(struct parse_events_terms *head_config, struct list_head *head_terms); +static int parse_events_terms__copy(const struct parse_events_terms *src, + struct parse_events_terms *dest); struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { [PERF_COUNT_HW_CPU_CYCLES] = { @@ -153,26 +154,27 @@ const char *event_type(int type) return "unknown"; } -static char *get_config_str(struct list_head *head_terms, enum parse_events__term_type type_term) +static char *get_config_str(struct parse_events_terms *head_terms, + enum parse_events__term_type type_term) { struct parse_events_term *term; if (!head_terms) return NULL; - list_for_each_entry(term, head_terms, list) + list_for_each_entry(term, &head_terms->terms, list) if (term->type_term == type_term) return term->val.str; return NULL; } -static char *get_config_metric_id(struct list_head *head_terms) +static char *get_config_metric_id(struct parse_events_terms *head_terms) { return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_METRIC_ID); } -static char *get_config_name(struct list_head *head_terms) +static char *get_config_name(struct parse_events_terms *head_terms) { return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_NAME); } @@ -188,11 +190,11 @@ static char *get_config_name(struct list_head *head_terms) * @config_terms: the list of terms that may contain a raw term. * @pmu: the PMU to scan for events from. */ -static void fix_raw(struct list_head *config_terms, struct perf_pmu *pmu) +static void fix_raw(struct parse_events_terms *config_terms, struct perf_pmu *pmu) { struct parse_events_term *term; - list_for_each_entry(term, config_terms, list) { + list_for_each_entry(term, &config_terms->terms, list) { u64 num; if (term->type_term != PARSE_EVENTS__TERM_TYPE_RAW) @@ -356,7 +358,7 @@ static int config_term_common(struct perf_event_attr *attr, struct parse_events_term *term, struct parse_events_error *err); static int config_attr(struct perf_event_attr *attr, - struct list_head *head, + struct parse_events_terms *head, struct parse_events_error *err, config_term_func_t config_term); @@ -442,7 +444,7 @@ bool parse_events__filter_pmu(const struct parse_events_state *parse_state, int parse_events_add_cache(struct list_head *list, int *idx, const char *name, struct parse_events_state *parse_state, - struct list_head *head_config) + struct parse_events_terms *head_config) { struct perf_pmu *pmu = NULL; bool found_supported = false; @@ -520,7 +522,7 @@ static void tracepoint_error(struct parse_events_error *e, int err, static int add_tracepoint(struct list_head *list, int *idx, const char *sys_name, const char *evt_name, struct parse_events_error *err, - struct list_head *head_config, void *loc_) + struct parse_events_terms *head_config, void *loc_) { YYLTYPE *loc = loc_; struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, (*idx)++); @@ -545,7 +547,7 @@ static int add_tracepoint(struct list_head *list, int *idx, static int add_tracepoint_multi_event(struct list_head *list, int *idx, const char *sys_name, const char *evt_name, struct parse_events_error *err, - struct list_head *head_config, YYLTYPE *loc) + struct parse_events_terms *head_config, YYLTYPE *loc) { char *evt_path; struct dirent *evt_ent; @@ -593,7 +595,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, static int add_tracepoint_event(struct list_head *list, int *idx, const char *sys_name, const char *evt_name, struct parse_events_error *err, - struct list_head *head_config, YYLTYPE *loc) + struct parse_events_terms *head_config, YYLTYPE *loc) { return strpbrk(evt_name, "*?") ? add_tracepoint_multi_event(list, idx, sys_name, evt_name, @@ -605,7 +607,7 @@ static int add_tracepoint_event(struct list_head *list, int *idx, static int add_tracepoint_multi_sys(struct list_head *list, int *idx, const char *sys_name, const char *evt_name, struct parse_events_error *err, - struct list_head *head_config, YYLTYPE *loc) + struct parse_events_terms *head_config, YYLTYPE *loc) { struct dirent *events_ent; DIR *events_dir; @@ -680,7 +682,7 @@ do { \ int parse_events_add_breakpoint(struct parse_events_state *parse_state, struct list_head *list, u64 addr, char *type, u64 len, - struct list_head *head_config __maybe_unused) + struct parse_events_terms *head_config) { struct perf_event_attr attr; LIST_HEAD(config_terms); @@ -1066,21 +1068,20 @@ static int config_term_tracepoint(struct perf_event_attr *attr, #endif static int config_attr(struct perf_event_attr *attr, - struct list_head *head, + struct parse_events_terms *head, struct parse_events_error *err, config_term_func_t config_term) { struct parse_events_term *term; - list_for_each_entry(term, head, list) + list_for_each_entry(term, &head->terms, list) if (config_term(attr, term, err)) return -EINVAL; return 0; } -static int get_config_terms(struct list_head *head_config, - struct list_head *head_terms __maybe_unused) +static int get_config_terms(struct parse_events_terms *head_config, struct list_head *head_terms) { #define ADD_CONFIG_TERM(__type, __weak) \ struct evsel_config_term *__t; \ @@ -1113,7 +1114,7 @@ do { \ struct parse_events_term *term; - list_for_each_entry(term, head_config, list) { + list_for_each_entry(term, &head_config->terms, list) { switch (term->type_term) { case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak); @@ -1194,14 +1195,14 @@ do { \ * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for * each bit of attr->config that the user has changed. */ -static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config, +static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head_config, struct list_head *head_terms) { struct parse_events_term *term; u64 bits = 0; int type; - list_for_each_entry(term, head_config, list) { + list_for_each_entry(term, &head_config->terms, list) { switch (term->type_term) { case PARSE_EVENTS__TERM_TYPE_USER: type = perf_pmu__format_type(pmu, term->config); @@ -1251,7 +1252,7 @@ static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config, int parse_events_add_tracepoint(struct list_head *list, int *idx, const char *sys, const char *event, struct parse_events_error *err, - struct list_head *head_config, void *loc_) + struct parse_events_terms *head_config, void *loc_) { YYLTYPE *loc = loc_; #ifdef HAVE_LIBTRACEEVENT @@ -1284,7 +1285,7 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx, static int __parse_events_add_numeric(struct parse_events_state *parse_state, struct list_head *list, struct perf_pmu *pmu, u32 type, u32 extended_type, - u64 config, struct list_head *head_config) + u64 config, struct parse_events_terms *head_config) { struct perf_event_attr attr; LIST_HEAD(config_terms); @@ -1320,7 +1321,7 @@ static int __parse_events_add_numeric(struct parse_events_state *parse_state, int parse_events_add_numeric(struct parse_events_state *parse_state, struct list_head *list, u32 type, u64 config, - struct list_head *head_config, + struct parse_events_terms *head_config, bool wildcard) { struct perf_pmu *pmu = NULL; @@ -1369,7 +1370,7 @@ static bool config_term_percore(struct list_head *config_terms) int parse_events_add_pmu(struct parse_events_state *parse_state, struct list_head *list, const char *name, - struct list_head *head_config, + const struct parse_events_terms *const_parsed_terms, bool auto_merge_stats, void *loc_) { struct perf_event_attr attr; @@ -1379,6 +1380,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, struct parse_events_error *err = parse_state->error; YYLTYPE *loc = loc_; LIST_HEAD(config_terms); + struct parse_events_terms parsed_terms; pmu = parse_state->fake_pmu ?: perf_pmus__find(name); @@ -1392,32 +1394,37 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, return -EINVAL; } + parse_events_terms__init(&parsed_terms); + if (const_parsed_terms) { + int ret = parse_events_terms__copy(const_parsed_terms, &parsed_terms); + + if (ret) + return ret; + } + if (verbose > 1) { struct strbuf sb; strbuf_init(&sb, /*hint=*/ 0); - if (pmu->selectable && !head_config) { + if (pmu->selectable && list_empty(&parsed_terms.terms)) { strbuf_addf(&sb, "%s//", name); } else { strbuf_addf(&sb, "%s/", name); - parse_events_term__to_strbuf(head_config, &sb); + parse_events_terms__to_strbuf(&parsed_terms, &sb); strbuf_addch(&sb, '/'); } fprintf(stderr, "Attempt to add: %s\n", sb.buf); strbuf_release(&sb); } - if (head_config) - fix_raw(head_config, pmu); + fix_raw(&parsed_terms, pmu); + + memset(&attr, 0, sizeof(attr)); + if (pmu->perf_event_attr_init_default) + pmu->perf_event_attr_init_default(pmu, &attr); - if (pmu->default_config) { - memcpy(&attr, pmu->default_config, - sizeof(struct perf_event_attr)); - } else { - memset(&attr, 0, sizeof(attr)); - } attr.type = pmu->type; - if (!head_config) { + if (list_empty(&parsed_terms.terms)) { evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true, /*name=*/NULL, /*metric_id=*/NULL, pmu, @@ -1426,14 +1433,16 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, return evsel ? 0 : -ENOMEM; } - if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info, err)) + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, &parsed_terms, &info, err)) { + parse_events_terms__exit(&parsed_terms); return -EINVAL; + } if (verbose > 1) { struct strbuf sb; strbuf_init(&sb, /*hint=*/ 0); - parse_events_term__to_strbuf(head_config, &sb); + parse_events_terms__to_strbuf(&parsed_terms, &sb); fprintf(stderr, "..after resolving event: %s/%s/\n", name, sb.buf); strbuf_release(&sb); } @@ -1442,39 +1451,53 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, * Configure hardcoded terms first, no need to check * return value when called with fail == 0 ;) */ - if (config_attr(&attr, head_config, parse_state->error, config_term_pmu)) + if (config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { + parse_events_terms__exit(&parsed_terms); return -EINVAL; + } - if (get_config_terms(head_config, &config_terms)) + if (get_config_terms(&parsed_terms, &config_terms)) { + parse_events_terms__exit(&parsed_terms); return -ENOMEM; + } /* * When using default config, record which bits of attr->config were * changed by the user. */ - if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) + if (pmu->perf_event_attr_init_default && + get_config_chgs(pmu, &parsed_terms, &config_terms)) { + parse_events_terms__exit(&parsed_terms); return -ENOMEM; + } - if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { + if (!parse_state->fake_pmu && + perf_pmu__config(pmu, &attr, &parsed_terms, parse_state->error)) { free_config_terms(&config_terms); + parse_events_terms__exit(&parsed_terms); return -EINVAL; } evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true, - get_config_name(head_config), - get_config_metric_id(head_config), pmu, + get_config_name(&parsed_terms), + get_config_metric_id(&parsed_terms), pmu, &config_terms, auto_merge_stats, /*cpu_list=*/NULL); - if (!evsel) + if (!evsel) { + parse_events_terms__exit(&parsed_terms); return -ENOMEM; + } if (evsel->name) evsel->use_config_name = true; evsel->percore = config_term_percore(&evsel->config_terms); - if (parse_state->fake_pmu) + if (parse_state->fake_pmu) { + parse_events_terms__exit(&parsed_terms); return 0; + } + parse_events_terms__exit(&parsed_terms); free((char *)evsel->unit); evsel->unit = strdup(info.unit); evsel->scale = info.scale; @@ -1484,27 +1507,29 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, } int parse_events_multi_pmu_add(struct parse_events_state *parse_state, - char *str, struct list_head *head, + const char *event_name, + const struct parse_events_terms *const_parsed_terms, struct list_head **listp, void *loc_) { struct parse_events_term *term; struct list_head *list = NULL; - struct list_head *orig_head = NULL; struct perf_pmu *pmu = NULL; YYLTYPE *loc = loc_; int ok = 0; const char *config; + struct parse_events_terms parsed_terms; *listp = NULL; - if (!head) { - head = malloc(sizeof(struct list_head)); - if (!head) - goto out_err; + parse_events_terms__init(&parsed_terms); + if (const_parsed_terms) { + int ret = parse_events_terms__copy(const_parsed_terms, &parsed_terms); - INIT_LIST_HEAD(head); + if (ret) + return ret; } - config = strdup(str); + + config = strdup(event_name); if (!config) goto out_err; @@ -1515,7 +1540,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, zfree(&config); goto out_err; } - list_add_tail(&term->list, head); + list_add_tail(&term->list, &parsed_terms.terms); /* Add it for all PMUs that support the alias */ list = malloc(sizeof(struct list_head)); @@ -1530,44 +1555,42 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, if (parse_events__filter_pmu(parse_state, pmu)) continue; - if (!perf_pmu__have_event(pmu, str)) + if (!perf_pmu__have_event(pmu, event_name)) continue; auto_merge_stats = perf_pmu__auto_merge_stats(pmu); - parse_events_copy_term_list(head, &orig_head); if (!parse_events_add_pmu(parse_state, list, pmu->name, - orig_head, auto_merge_stats, loc)) { + &parsed_terms, auto_merge_stats, loc)) { struct strbuf sb; strbuf_init(&sb, /*hint=*/ 0); - parse_events_term__to_strbuf(orig_head, &sb); - pr_debug("%s -> %s/%s/\n", str, pmu->name, sb.buf); + parse_events_terms__to_strbuf(&parsed_terms, &sb); + pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf); strbuf_release(&sb); ok++; } - parse_events_terms__delete(orig_head); } if (parse_state->fake_pmu) { - if (!parse_events_add_pmu(parse_state, list, str, head, + if (!parse_events_add_pmu(parse_state, list, event_name, &parsed_terms, /*auto_merge_stats=*/true, loc)) { struct strbuf sb; strbuf_init(&sb, /*hint=*/ 0); - parse_events_term__to_strbuf(head, &sb); - pr_debug("%s -> %s/%s/\n", str, "fake_pmu", sb.buf); + parse_events_terms__to_strbuf(&parsed_terms, &sb); + pr_debug("%s -> %s/%s/\n", event_name, "fake_pmu", sb.buf); strbuf_release(&sb); ok++; } } out_err: + parse_events_terms__exit(&parsed_terms); if (ok) *listp = list; else free(list); - parse_events_terms__delete(head); return ok ? 0 : -1; } @@ -1832,7 +1855,7 @@ static int parse_events__scanner(const char *str, /* * parse event config string, return a list of event terms. */ -int parse_events_terms(struct list_head *terms, const char *str, FILE *input) +int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input) { struct parse_events_state parse_state = { .terms = NULL, @@ -1841,14 +1864,10 @@ int parse_events_terms(struct list_head *terms, const char *str, FILE *input) int ret; ret = parse_events__scanner(str, input, &parse_state); + if (!ret) + list_splice(&parse_state.terms->terms, &terms->terms); - if (!ret) { - list_splice(parse_state.terms, terms); - zfree(&parse_state.terms); - return 0; - } - - parse_events_terms__delete(parse_state.terms); + zfree(&parse_state.terms); return ret; } @@ -2530,8 +2549,10 @@ int parse_events_term__clone(struct parse_events_term **new, return new_term(new, &temp, /*str=*/NULL, term->val.num); str = strdup(term->val.str); - if (!str) + if (!str) { + zfree(&temp.config); return -ENOMEM; + } return new_term(new, &temp, str, /*num=*/0); } @@ -2544,58 +2565,56 @@ void parse_events_term__delete(struct parse_events_term *term) free(term); } -int parse_events_copy_term_list(struct list_head *old, - struct list_head **new) +static int parse_events_terms__copy(const struct parse_events_terms *src, + struct parse_events_terms *dest) { - struct parse_events_term *term, *n; - int ret; + struct parse_events_term *term; - if (!old) { - *new = NULL; - return 0; - } + list_for_each_entry (term, &src->terms, list) { + struct parse_events_term *n; + int ret; - *new = malloc(sizeof(struct list_head)); - if (!*new) - return -ENOMEM; - INIT_LIST_HEAD(*new); - - list_for_each_entry (term, old, list) { ret = parse_events_term__clone(&n, term); if (ret) return ret; - list_add_tail(&n->list, *new); + + list_add_tail(&n->list, &dest->terms); } return 0; } -void parse_events_terms__purge(struct list_head *terms) +void parse_events_terms__init(struct parse_events_terms *terms) +{ + INIT_LIST_HEAD(&terms->terms); +} + +void parse_events_terms__exit(struct parse_events_terms *terms) { struct parse_events_term *term, *h; - list_for_each_entry_safe(term, h, terms, list) { + list_for_each_entry_safe(term, h, &terms->terms, list) { list_del_init(&term->list); parse_events_term__delete(term); } } -void parse_events_terms__delete(struct list_head *terms) +void parse_events_terms__delete(struct parse_events_terms *terms) { if (!terms) return; - parse_events_terms__purge(terms); + parse_events_terms__exit(terms); free(terms); } -int parse_events_term__to_strbuf(struct list_head *term_list, struct strbuf *sb) +int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb) { struct parse_events_term *term; bool first = true; - if (!term_list) + if (!terms) return 0; - list_for_each_entry(term, term_list, list) { + list_for_each_entry(term, &terms->terms, list) { int ret; if (!first) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 594e5d2dc67f..63c0a36a4bf1 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -44,7 +44,6 @@ static inline int parse_events(struct evlist *evlist, const char *str, int parse_event(struct evlist *evlist, const char *str); -int parse_events_terms(struct list_head *terms, const char *str, FILE *input); int parse_filter(const struct option *opt, const char *str, int unset); int exclude_perf(const struct option *opt, const char *arg, int unset); @@ -140,6 +139,11 @@ struct parse_events_error { char *first_help; }; +/* A wrapper around a list of terms for the sake of better type safety. */ +struct parse_events_terms { + struct list_head terms; +}; + struct parse_events_state { /* The list parsed events are placed on. */ struct list_head list; @@ -148,7 +152,7 @@ struct parse_events_state { /* Error information. */ struct parse_events_error *error; /* Holds returned terms for term parsing. */ - struct list_head *terms; + struct parse_events_terms *terms; /* Start token. */ int stoken; /* Special fake PMU marker for testing. */ @@ -181,35 +185,38 @@ int parse_events_term__term(struct parse_events_term **term, int parse_events_term__clone(struct parse_events_term **new, struct parse_events_term *term); void parse_events_term__delete(struct parse_events_term *term); -void parse_events_terms__delete(struct list_head *terms); -void parse_events_terms__purge(struct list_head *terms); -int parse_events_term__to_strbuf(struct list_head *term_list, struct strbuf *sb); + +void parse_events_terms__delete(struct parse_events_terms *terms); +void parse_events_terms__init(struct parse_events_terms *terms); +void parse_events_terms__exit(struct parse_events_terms *terms); +int parse_events_terms(struct parse_events_terms *terms, const char *str, FILE *input); +int parse_events_terms__to_strbuf(const struct parse_events_terms *terms, struct strbuf *sb); int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_group(struct list_head *list, char *event_mod); int parse_events_name(struct list_head *list, const char *name); int parse_events_add_tracepoint(struct list_head *list, int *idx, const char *sys, const char *event, struct parse_events_error *error, - struct list_head *head_config, void *loc); + struct parse_events_terms *head_config, void *loc); int parse_events_add_numeric(struct parse_events_state *parse_state, struct list_head *list, u32 type, u64 config, - struct list_head *head_config, + struct parse_events_terms *head_config, bool wildcard); int parse_events_add_tool(struct parse_events_state *parse_state, struct list_head *list, int tool_event); int parse_events_add_cache(struct list_head *list, int *idx, const char *name, struct parse_events_state *parse_state, - struct list_head *head_config); + struct parse_events_terms *head_config); int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config); int parse_events_add_breakpoint(struct parse_events_state *parse_state, struct list_head *list, u64 addr, char *type, u64 len, - struct list_head *head_config); + struct parse_events_terms *head_config); int parse_events_add_pmu(struct parse_events_state *parse_state, struct list_head *list, const char *name, - struct list_head *head_config, + const struct parse_events_terms *const_parsed_terms, bool auto_merge_stats, void *loc); struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, @@ -217,13 +224,10 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, struct perf_pmu *pmu); int parse_events_multi_pmu_add(struct parse_events_state *parse_state, - char *str, - struct list_head *head_config, + const char *event_name, + const struct parse_events_terms *const_parsed_terms, struct list_head **listp, void *loc); -int parse_events_copy_term_list(struct list_head *old, - struct list_head **new); - void parse_events__set_leader(char *name, struct list_head *list); void parse_events_update_lists(struct list_head *list_event, struct list_head *list_all); diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 4ef4b6f171a0..e86c45675e1d 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -120,7 +120,7 @@ static int term(yyscan_t scanner, enum parse_events__term_type type) { YYSTYPE *yylval = parse_events_get_lval(scanner); - yylval->num = type; + yylval->term_type = type; return PE_TERM; } @@ -156,8 +156,8 @@ event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* event [^,{}/]+ num_dec [0-9]+ -num_hex 0x[a-fA-F0-9]+ -num_raw_hex [a-fA-F0-9]+ +num_hex 0x[a-fA-F0-9]{1,16} +num_raw_hex [a-fA-F0-9]{1,16} name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]!\-]* name_tag [\'][a-zA-Z_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\'] name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 21bfe7e0d944..de098caf0c1c 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -6,14 +6,13 @@ %{ +#ifndef NDEBUG #define YYDEBUG 1 +#endif #include -#include -#include #include #include -#include #include "pmu.h" #include "pmus.h" #include "evsel.h" @@ -70,7 +69,7 @@ static void free_list_evsel(struct list_head* list_evsel) %type PE_VALUE_SYM_HW %type PE_VALUE_SYM_SW %type PE_VALUE_SYM_TOOL -%type PE_TERM +%type PE_TERM %type value_sym %type PE_RAW %type PE_NAME @@ -79,7 +78,7 @@ static void free_list_evsel(struct list_head* list_evsel) %type PE_MODIFIER_BP %type PE_EVENT_NAME %type PE_DRV_CFG_TERM -%type name_or_raw name_or_legacy +%type name_or_raw %destructor { free ($$); } %type event_term %destructor { parse_events_term__delete ($$); } @@ -104,6 +103,7 @@ static void free_list_evsel(struct list_head* list_evsel) %type groups %destructor { free_list_evsel ($$); } %type tracepoint_name +%destructor { free ($$.sys); free ($$.event); } %type PE_TERM_HW %destructor { free ($$.str); } @@ -111,8 +111,9 @@ static void free_list_evsel(struct list_head* list_evsel) { char *str; u64 num; + enum parse_events__term_type term_type; struct list_head *list_evsel; - struct list_head *list_terms; + struct parse_events_terms *list_terms; struct parse_events_term *term; struct tracepoint_name { char *sys; @@ -273,23 +274,18 @@ event_pmu: PE_NAME opt_pmu_config { struct parse_events_state *parse_state = _parse_state; - struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL; + /* List of created evsels. */ + struct list_head *list = NULL; char *pattern = NULL; #define CLEANUP \ do { \ parse_events_terms__delete($2); \ - parse_events_terms__delete(orig_terms); \ free(list); \ free($1); \ free(pattern); \ } while(0) - if (parse_events_copy_term_list($2, &orig_terms)) { - CLEANUP; - YYNOMEM; - } - list = alloc_list(); if (!list) { CLEANUP; @@ -319,16 +315,11 @@ PE_NAME opt_pmu_config !perf_pmu__match(pattern, pmu->alias_name, $1)) { bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu); - if (parse_events_copy_term_list(orig_terms, &terms)) { - CLEANUP; - YYNOMEM; - } - if (!parse_events_add_pmu(parse_state, list, pmu->name, terms, + if (!parse_events_add_pmu(parse_state, list, pmu->name, $2, auto_merge_stats, &@1)) { ok++; parse_state->wild_card_pmus = true; } - parse_events_terms__delete(terms); } } @@ -336,7 +327,6 @@ PE_NAME opt_pmu_config /* Failure to add, assume $1 is an event name. */ zfree(&list); ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1); - $2 = NULL; } if (!ok) { struct parse_events_error *error = parse_state->error; @@ -654,33 +644,31 @@ start_terms: event_config event_config: event_config ',' event_term { - struct list_head *head = $1; + struct parse_events_terms *head = $1; struct parse_events_term *term = $3; if (!head) { parse_events_term__delete(term); YYABORT; } - list_add_tail(&term->list, head); + list_add_tail(&term->list, &head->terms); $$ = $1; } | event_term { - struct list_head *head = malloc(sizeof(*head)); + struct parse_events_terms *head = malloc(sizeof(*head)); struct parse_events_term *term = $1; if (!head) YYNOMEM; - INIT_LIST_HEAD(head); - list_add_tail(&term->list, head); + parse_events_terms__init(head); + list_add_tail(&term->list, &head->terms); $$ = head; } name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE -name_or_legacy: PE_NAME | PE_LEGACY_CACHE - event_term: PE_RAW { @@ -695,7 +683,7 @@ PE_RAW $$ = term; } | -name_or_raw '=' name_or_legacy +name_or_raw '=' name_or_raw { struct parse_events_term *term; int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); @@ -775,11 +763,10 @@ PE_TERM_HW $$ = term; } | -PE_TERM '=' name_or_legacy +PE_TERM '=' name_or_raw { struct parse_events_term *term; - int err = parse_events_term__str(&term, (enum parse_events__term_type)$1, - /*config=*/NULL, $3, &@1, &@3); + int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3); if (err) { free($3); @@ -791,8 +778,7 @@ PE_TERM '=' name_or_legacy PE_TERM '=' PE_TERM_HW { struct parse_events_term *term; - int err = parse_events_term__str(&term, (enum parse_events__term_type)$1, - /*config=*/NULL, $3.str, &@1, &@3); + int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3.str, &@1, &@3); if (err) { free($3.str); @@ -804,10 +790,7 @@ PE_TERM '=' PE_TERM_HW PE_TERM '=' PE_TERM { struct parse_events_term *term; - int err = parse_events_term__term(&term, - (enum parse_events__term_type)$1, - (enum parse_events__term_type)$3, - &@1, &@3); + int err = parse_events_term__term(&term, $1, $3, &@1, &@3); if (err) PE_ABORT(err); @@ -818,8 +801,9 @@ PE_TERM '=' PE_TERM PE_TERM '=' PE_VALUE { struct parse_events_term *term; - int err = parse_events_term__num(&term, (enum parse_events__term_type)$1, - /*config=*/NULL, $3, /*novalue=*/false, &@1, &@3); + int err = parse_events_term__num(&term, $1, + /*config=*/NULL, $3, /*novalue=*/false, + &@1, &@3); if (err) PE_ABORT(err); @@ -830,9 +814,9 @@ PE_TERM '=' PE_VALUE PE_TERM { struct parse_events_term *term; - int err = parse_events_term__num(&term, (enum parse_events__term_type)$1, - /*config=*/NULL, /*num=*/1, /*novalue=*/true, - &@1, /*loc_val=*/NULL); + int err = parse_events_term__num(&term, $1, + /*config=*/NULL, /*num=*/1, /*novalue=*/true, + &@1, /*loc_val=*/NULL); if (err) PE_ABORT(err); diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c index 862e4a689868..5ccfe4b64cdf 100644 --- a/tools/perf/util/pfm.c +++ b/tools/perf/util/pfm.c @@ -145,7 +145,20 @@ static bool is_libpfm_event_supported(const char *name, struct perf_cpu_map *cpu evsel->is_libpfm_event = true; - if (evsel__open(evsel, cpus, threads) < 0) + ret = evsel__open(evsel, cpus, threads); + if (ret == -EACCES) { + /* + * This happens if the paranoid value + * /proc/sys/kernel/perf_event_paranoid is set to 2 + * Re-run with exclude_kernel set; we don't do that + * by default as some ARM machines do not support it. + * + */ + evsel->core.attr.exclude_kernel = 1; + ret = evsel__open(evsel, cpus, threads); + + } + if (ret < 0) result = false; evsel__close(evsel); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d515ba8a0e16..d3c9aa4326be 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -28,6 +28,7 @@ #include "strbuf.h" #include "fncache.h" #include "util/evsel_config.h" +#include struct perf_pmu perf_pmu__fake = { .name = "fake", @@ -52,7 +53,7 @@ struct perf_pmu_alias { */ char *topic; /** @terms: Owned list of the original parsed parameters. */ - struct list_head terms; + struct parse_events_terms terms; /** @list: List element of struct perf_pmu aliases. */ struct list_head list; /** @@ -155,7 +156,7 @@ static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file) format->loaded = true; } -static void perf_pmu_format__load(struct perf_pmu *pmu, struct perf_pmu_format *format) +static void perf_pmu_format__load(const struct perf_pmu *pmu, struct perf_pmu_format *format) { char path[PATH_MAX]; FILE *file = NULL; @@ -404,7 +405,7 @@ static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) zfree(&newalias->long_desc); zfree(&newalias->topic); zfree(&newalias->pmu_name); - parse_events_terms__purge(&newalias->terms); + parse_events_terms__exit(&newalias->terms); free(newalias); } @@ -484,7 +485,7 @@ static int update_alias(const struct pmu_event *pe, assign_str(pe->name, "topic", &data->alias->topic, pe->topic); data->alias->per_pkg = pe->perpkg; if (pe->event) { - parse_events_terms__purge(&data->alias->terms); + parse_events_terms__exit(&data->alias->terms); ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL); } if (!ret && pe->unit) { @@ -524,7 +525,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, if (!alias) return -ENOMEM; - INIT_LIST_HEAD(&alias->terms); + parse_events_terms__init(&alias->terms); alias->scale = 1.0; alias->unit[0] = '\0'; alias->per_pkg = perpkg; @@ -574,7 +575,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, return 0; } -static inline bool pmu_alias_info_file(char *name) +static inline bool pmu_alias_info_file(const char *name) { size_t len; @@ -656,17 +657,17 @@ static int pmu_aliases_parse(struct perf_pmu *pmu) return 0; } -static int pmu_alias_terms(struct perf_pmu_alias *alias, - struct list_head *terms) +static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms) { struct parse_events_term *term, *cloned; - LIST_HEAD(list); - int ret; + struct parse_events_terms clone_terms; + + parse_events_terms__init(&clone_terms); + list_for_each_entry(term, &alias->terms.terms, list) { + int ret = parse_events_term__clone(&cloned, term); - list_for_each_entry(term, &alias->terms, list) { - ret = parse_events_term__clone(&cloned, term); if (ret) { - parse_events_terms__purge(&list); + parse_events_terms__exit(&clone_terms); return ret; } /* @@ -674,9 +675,10 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, * which we don't want for implicit terms in aliases. */ cloned->weak = true; - list_add_tail(&cloned->list, &list); + list_add_tail(&cloned->list, &clone_terms.terms); } - list_splice(&list, terms); + list_splice_init(&clone_terms.terms, terms); + parse_events_terms__exit(&clone_terms); return 0; } @@ -775,11 +777,6 @@ char *perf_pmu__getcpuid(struct perf_pmu *pmu) return cpuid; } -__weak const struct pmu_events_table *pmu_events_table__find(void) -{ - return perf_pmu__find_events_table(NULL); -} - __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) { return perf_pmu__find_metrics_table(NULL); @@ -874,6 +871,28 @@ out: return res; } +bool pmu_uncore_identifier_match(const char *compat, const char *id) +{ + regex_t re; + regmatch_t pmatch[1]; + int match; + + if (regcomp(&re, compat, REG_EXTENDED) != 0) { + /* Warn unable to generate match particular string. */ + pr_info("Invalid regular expression %s\n", compat); + return false; + } + + match = !regexec(&re, id, 1, pmatch, 0); + if (match) { + /* Ensure a full match. */ + match = pmatch[0].rm_so == 0 && (size_t)pmatch[0].rm_eo == strlen(id); + } + regfree(&re); + + return match; +} + static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, const struct pmu_events_table *table __maybe_unused, void *vdata) @@ -914,8 +933,8 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, if (!pe->compat || !pe->pmu) return 0; - if (!strcmp(pmu->id, pe->compat) && - pmu_uncore_alias_match(pe->pmu, pmu->name)) { + if (pmu_uncore_alias_match(pe->pmu, pmu->name) && + pmu_uncore_identifier_match(pe->compat, pmu->id)) { perf_pmu__new_alias(pmu, pe->name, pe->desc, @@ -935,22 +954,27 @@ void pmu_add_sys_aliases(struct perf_pmu *pmu) pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, pmu); } -struct perf_event_attr * __weak -perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) +static char *pmu_find_alias_name(struct perf_pmu *pmu, int dirfd) { - return NULL; -} + FILE *file = perf_pmu__open_file_at(pmu, dirfd, "alias"); + char *line = NULL; + size_t line_len = 0; + ssize_t ret; -const char * __weak -pmu_find_real_name(const char *name) -{ - return name; -} + if (!file) + return NULL; -const char * __weak -pmu_find_alias_name(const char *name __maybe_unused) -{ - return NULL; + ret = getline(&line, &line_len, file); + if (ret < 0) { + fclose(file); + return NULL; + } + /* Remove trailing newline. */ + if (ret > 0 && line[ret - 1] == '\n') + line[--ret] = '\0'; + + fclose(file); + return line; } static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) @@ -961,12 +985,15 @@ static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) return max_precise; } -struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) +void __weak +perf_pmu__arch_init(struct perf_pmu *pmu __maybe_unused) +{ +} + +struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *name) { struct perf_pmu *pmu; __u32 type; - const char *name = pmu_find_real_name(lookup_name); - const char *alias_name; pmu = zalloc(sizeof(*pmu)); if (!pmu) @@ -999,23 +1026,17 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char pmu->is_core = is_pmu_core(name); pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); - alias_name = pmu_find_alias_name(name); - if (alias_name) { - pmu->alias_name = strdup(alias_name); - if (!pmu->alias_name) - goto err; - } - pmu->type = type; pmu->is_uncore = pmu_is_uncore(dirfd, name); if (pmu->is_uncore) pmu->id = pmu_id(name); pmu->max_precise = pmu_max_precise(dirfd, pmu); + pmu->alias_name = pmu_find_alias_name(pmu, dirfd); pmu->events_table = perf_pmu__find_events_table(pmu); pmu_add_sys_aliases(pmu); list_add_tail(&pmu->list, pmus); - pmu->default_config = perf_pmu__get_default_config(pmu); + perf_pmu__arch_init(pmu); return pmu; err: @@ -1110,7 +1131,7 @@ void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, } static struct perf_pmu_format * -pmu_find_format(struct list_head *formats, const char *name) +pmu_find_format(const struct list_head *formats, const char *name) { struct perf_pmu_format *format; @@ -1188,12 +1209,12 @@ static __u64 pmu_format_max_value(const unsigned long *format) * in a config string) later on in the term list. */ static int pmu_resolve_param_term(struct parse_events_term *term, - struct list_head *head_terms, + struct parse_events_terms *head_terms, __u64 *value) { struct parse_events_term *t; - list_for_each_entry(t, head_terms, list) { + list_for_each_entry(t, &head_terms->terms, list) { if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && t->config && !strcmp(t->config, term->config)) { t->used = true; @@ -1208,7 +1229,7 @@ static int pmu_resolve_param_term(struct parse_events_term *term, return -1; } -static char *pmu_formats_string(struct list_head *formats) +static char *pmu_formats_string(const struct list_head *formats) { struct perf_pmu_format *format; char *str = NULL; @@ -1234,10 +1255,10 @@ error: * Setup one of config[12] attr members based on the * user input data - term parameter. */ -static int pmu_config_term(struct perf_pmu *pmu, +static int pmu_config_term(const struct perf_pmu *pmu, struct perf_event_attr *attr, struct parse_events_term *term, - struct list_head *head_terms, + struct parse_events_terms *head_terms, bool zero, struct parse_events_error *err) { struct perf_pmu_format *format; @@ -1357,15 +1378,15 @@ static int pmu_config_term(struct perf_pmu *pmu, return 0; } -int perf_pmu__config_terms(struct perf_pmu *pmu, +int perf_pmu__config_terms(const struct perf_pmu *pmu, struct perf_event_attr *attr, - struct list_head *head_terms, + struct parse_events_terms *terms, bool zero, struct parse_events_error *err) { struct parse_events_term *term; - list_for_each_entry(term, head_terms, list) { - if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) + list_for_each_entry(term, &terms->terms, list) { + if (pmu_config_term(pmu, attr, term, terms, zero, err)) return -EINVAL; } @@ -1378,10 +1399,10 @@ int perf_pmu__config_terms(struct perf_pmu *pmu, * 2) pmu format definitions - specified by pmu parameter */ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, - struct list_head *head_terms, + struct parse_events_terms *head_terms, struct parse_events_error *err) { - bool zero = !!pmu->default_config; + bool zero = !!pmu->perf_event_attr_init_default; return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); } @@ -1472,7 +1493,7 @@ static int check_info_data(struct perf_pmu *pmu, * Find alias in the terms list and replace it with the terms * defined for the alias */ -int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, +int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, struct perf_pmu_info *info, struct parse_events_error *err) { struct parse_events_term *term, *h; @@ -1489,7 +1510,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, info->scale = 0.0; info->snapshot = false; - list_for_each_entry_safe(term, h, head_terms, list) { + list_for_each_entry_safe(term, h, &head_terms->terms, list) { alias = pmu_find_alias(pmu, term); if (!alias) continue; @@ -1634,7 +1655,7 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, : (int)strlen(pmu->name); int used = snprintf(buf, len, "%.*s/%s", pmu_name_len, pmu->name, alias->name); - list_for_each_entry(term, &alias->terms, list) { + list_for_each_entry(term, &alias->terms.terms, list) { if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) used += snprintf(buf + used, sub_non_neg(len, used), ",%s=%s", term->config, @@ -1693,7 +1714,7 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, info.desc = event->desc; info.long_desc = event->long_desc; info.encoding_desc = buf + buf_used; - parse_events_term__to_strbuf(&event->terms, &sb); + parse_events_terms__to_strbuf(&event->terms, &sb); buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, "%s/%s/", info.pmu_name, sb.buf) + 1; info.topic = event->topic; @@ -1749,7 +1770,7 @@ bool perf_pmu__is_software(const struct perf_pmu *pmu) return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe"); } -FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) +FILE *perf_pmu__open_file(const struct perf_pmu *pmu, const char *name) { char path[PATH_MAX]; @@ -1760,7 +1781,7 @@ FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) return fopen(path, "r"); } -FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) +FILE *perf_pmu__open_file_at(const struct perf_pmu *pmu, int dirfd, const char *name) { int fd; @@ -1771,7 +1792,7 @@ FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) return fdopen(fd, "r"); } -int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, +int perf_pmu__scan_file(const struct perf_pmu *pmu, const char *name, const char *fmt, ...) { va_list args; @@ -1788,7 +1809,7 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, return ret; } -int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, +int perf_pmu__scan_file_at(const struct perf_pmu *pmu, int dirfd, const char *name, const char *fmt, ...) { va_list args; @@ -1805,7 +1826,7 @@ int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, return ret; } -bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) +bool perf_pmu__file_exists(const struct perf_pmu *pmu, const char *name) { char path[PATH_MAX]; @@ -2043,26 +2064,8 @@ void perf_pmu__delete(struct perf_pmu *pmu) perf_cpu_map__put(pmu->cpus); - zfree(&pmu->default_config); zfree(&pmu->name); zfree(&pmu->alias_name); zfree(&pmu->id); free(pmu); } - -struct perf_pmu *pmu__find_core_pmu(void) -{ - struct perf_pmu *pmu = NULL; - - while ((pmu = perf_pmus__scan_core(pmu))) { - /* - * The cpumap should cover all CPUs. Otherwise, some CPUs may - * not support some events or have different event IDs. - */ - if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu) - return NULL; - - return pmu; - } - return NULL; -} diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 6a4e170c61d6..d2895d415f08 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -92,10 +92,11 @@ struct perf_pmu { */ int max_precise; /** - * @default_config: Optional default perf_event_attr determined in - * architecture specific code. + * @perf_event_attr_init_default: Optional function to default + * initialize PMU specific parts of the perf_event_attr. */ - struct perf_event_attr *default_config; + void (*perf_event_attr_init_default)(const struct perf_pmu *pmu, + struct perf_event_attr *attr); /** * @cpus: Empty or the contents of either of: * /bus/event_source/devices//cpumask. @@ -191,15 +192,15 @@ typedef int (*pmu_event_callback)(void *state, struct pmu_event_info *info); void pmu_add_sys_aliases(struct perf_pmu *pmu); int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, - struct list_head *head_terms, + struct parse_events_terms *head_terms, struct parse_events_error *error); -int perf_pmu__config_terms(struct perf_pmu *pmu, +int perf_pmu__config_terms(const struct perf_pmu *pmu, struct perf_event_attr *attr, - struct list_head *head_terms, + struct parse_events_terms *terms, bool zero, struct parse_events_error *error); __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name); int perf_pmu__format_type(struct perf_pmu *pmu, const char *name); -int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, +int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, struct perf_pmu_info *info, struct parse_events_error *err); int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb); @@ -222,24 +223,25 @@ bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name); */ bool perf_pmu__is_software(const struct perf_pmu *pmu); -FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name); -FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name); +FILE *perf_pmu__open_file(const struct perf_pmu *pmu, const char *name); +FILE *perf_pmu__open_file_at(const struct perf_pmu *pmu, int dirfd, const char *name); -int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4); -int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, +int perf_pmu__scan_file(const struct perf_pmu *pmu, const char *name, const char *fmt, ...) + __scanf(3, 4); +int perf_pmu__scan_file_at(const struct perf_pmu *pmu, int dirfd, const char *name, const char *fmt, ...) __scanf(4, 5); -bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name); +bool perf_pmu__file_exists(const struct perf_pmu *pmu, const char *name); int perf_pmu__test(void); -struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu); +void perf_pmu__arch_init(struct perf_pmu *pmu); void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table); char *perf_pmu__getcpuid(struct perf_pmu *pmu); -const struct pmu_events_table *pmu_events_table__find(void); const struct pmu_metrics_table *pmu_metrics_table__find(void); +bool pmu_uncore_identifier_match(const char *compat, const char *id); int perf_pmu__convert_scale(const char *scale, char **end, double *sval); @@ -252,8 +254,6 @@ void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu); int perf_pmu__match(const char *pattern, const char *name, const char *tok); -const char *pmu_find_real_name(const char *name); -const char *pmu_find_alias_name(const char *name); double perf_pmu__cpu_slots_per_cycle(void); int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size); int perf_pmu__pathname_scnprintf(char *buf, size_t size, @@ -264,6 +264,6 @@ int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name); struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus); void perf_pmu__delete(struct perf_pmu *pmu); -struct perf_pmu *pmu__find_core_pmu(void); +struct perf_pmu *perf_pmus__find_core_pmu(void); #endif /* __PMU_H */ diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y index 600c8c158c8e..198907a8a48a 100644 --- a/tools/perf/util/pmu.y +++ b/tools/perf/util/pmu.y @@ -5,6 +5,10 @@ %{ +#ifndef NDEBUG +#define YYDEBUG 1 +#endif + #include #include #include diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c index 6631367c756f..ce4931461741 100644 --- a/tools/perf/util/pmus.c +++ b/tools/perf/util/pmus.c @@ -10,6 +10,7 @@ #include #include #include +#include "cpumap.h" #include "debug.h" #include "evsel.h" #include "pmus.h" @@ -36,6 +37,8 @@ static LIST_HEAD(other_pmus); static bool read_sysfs_core_pmus; static bool read_sysfs_all_pmus; +static void pmu_read_sysfs(bool core_only); + int pmu_name_len_no_suffix(const char *str, unsigned long *num) { int orig_len, len; @@ -123,6 +126,14 @@ struct perf_pmu *perf_pmus__find(const char *name) pmu = perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name); close(dirfd); + if (!pmu) { + /* + * Looking up an inidividual PMU failed. This may mean name is + * an alias, so read the PMUs from sysfs and try to find again. + */ + pmu_read_sysfs(core_pmu); + pmu = pmu_find(name); + } return pmu; } @@ -268,7 +279,7 @@ struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu) { if (!pmu) { pmu_read_sysfs(/*core_only=*/true); - pmu = list_prepare_entry(pmu, &core_pmus, list); + return list_first_entry_or_null(&core_pmus, typeof(*pmu), list); } list_for_each_entry_continue(pmu, &core_pmus, list) return pmu; @@ -592,3 +603,8 @@ struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) } return pmu; } + +struct perf_pmu *perf_pmus__find_core_pmu(void) +{ + return perf_pmus__scan_core(NULL); +} diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index a7566edc86a3..b0fc48be623f 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -395,6 +395,8 @@ void print_symbol_events(const struct print_callbacks *print_cb, void *print_sta */ void print_events(const struct print_callbacks *print_cb, void *print_state) { + char *tmp; + print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE, event_symbols_hw, PERF_COUNT_HW_MAX); print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE, @@ -418,17 +420,21 @@ void print_events(const struct print_callbacks *print_cb, void *print_state) /*long_desc=*/NULL, /*encoding_desc=*/NULL); - print_cb->print_event(print_state, - /*topic=*/NULL, - /*pmu_name=*/NULL, - "cpu/t1=v1[,t2=v2,t3 ...]/modifier", - /*event_alias=*/NULL, - /*scale_unit=*/NULL, - /*deprecated=*/false, - event_type_descriptors[PERF_TYPE_RAW], - "(see 'man perf-list' on how to encode it)", - /*long_desc=*/NULL, - /*encoding_desc=*/NULL); + if (asprintf(&tmp, "%s/t1=v1[,t2=v2,t3 ...]/modifier", + perf_pmus__scan_core(/*pmu=*/NULL)->name) > 0) { + print_cb->print_event(print_state, + /*topic=*/NULL, + /*pmu_name=*/NULL, + tmp, + /*event_alias=*/NULL, + /*scale_unit=*/NULL, + /*deprecated=*/false, + event_type_descriptors[PERF_TYPE_RAW], + "(see 'man perf-list' on how to encode it)", + /*long_desc=*/NULL, + /*encoding_desc=*/NULL); + free(tmp); + } print_cb->print_event(print_state, /*topic=*/NULL, diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 26e1c8d973ea..593b660ec75e 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -40,6 +40,7 @@ util/rwsem.c util/hashmap.c util/perf_regs.c util/fncache.c +util/rlimit.c util/perf-regs-arch/perf_regs_aarch64.c util/perf-regs-arch/perf_regs_arm.c util/perf-regs-arch/perf_regs_csky.c diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index c29f5f0bb552..8761f51b5c7c 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -98,7 +98,7 @@ struct perf_pmu *evsel__find_pmu(const struct evsel *evsel __maybe_unused) return NULL; } -int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) +int perf_pmu__scan_file(const struct perf_pmu *pmu, const char *name, const char *fmt, ...) { return EOF; } diff --git a/tools/perf/util/rlimit.c b/tools/perf/util/rlimit.c index 13521d392a22..f857405fe1aa 100644 --- a/tools/perf/util/rlimit.c +++ b/tools/perf/util/rlimit.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1 */ +#include #include "util/debug.h" #include "util/rlimit.h" #include @@ -27,3 +28,30 @@ void rlimit__bump_memlock(void) } } } + +bool rlimit__increase_nofile(enum rlimit_action *set_rlimit) +{ + int old_errno; + struct rlimit l; + + if (*set_rlimit < INCREASED_MAX) { + old_errno = errno; + + if (getrlimit(RLIMIT_NOFILE, &l) == 0) { + if (*set_rlimit == NO_CHANGE) { + l.rlim_cur = l.rlim_max; + } else { + l.rlim_cur = l.rlim_max + 1000; + l.rlim_max = l.rlim_cur; + } + if (setrlimit(RLIMIT_NOFILE, &l) == 0) { + (*set_rlimit) += 1; + errno = old_errno; + return true; + } + } + errno = old_errno; + } + + return false; +} diff --git a/tools/perf/util/rlimit.h b/tools/perf/util/rlimit.h index 9f59d8e710a3..19050d7fb9d7 100644 --- a/tools/perf/util/rlimit.h +++ b/tools/perf/util/rlimit.h @@ -1,6 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ #ifndef __PERF_RLIMIT_H_ #define __PERF_RLIMIT_H_ -/* SPDX-License-Identifier: LGPL-2.1 */ + +enum rlimit_action { + NO_CHANGE, + SET_TO_MAX, + INCREASED_MAX +}; void rlimit__bump_memlock(void); + +bool rlimit__increase_nofile(enum rlimit_action *set_rlimit); + #endif // __PERF_RLIMIT_H_ diff --git a/tools/perf/util/rwsem.c b/tools/perf/util/rwsem.c index f3d29d8ddc99..5109167f27f7 100644 --- a/tools/perf/util/rwsem.c +++ b/tools/perf/util/rwsem.c @@ -2,32 +2,66 @@ #include "util.h" #include "rwsem.h" +#if RWS_ERRORCHECK +#include "mutex.h" +#endif + int init_rwsem(struct rw_semaphore *sem) { +#if RWS_ERRORCHECK + mutex_init(&sem->mtx); + return 0; +#else return pthread_rwlock_init(&sem->lock, NULL); +#endif } int exit_rwsem(struct rw_semaphore *sem) { +#if RWS_ERRORCHECK + mutex_destroy(&sem->mtx); + return 0; +#else return pthread_rwlock_destroy(&sem->lock); +#endif } int down_read(struct rw_semaphore *sem) { +#if RWS_ERRORCHECK + mutex_lock(&sem->mtx); + return 0; +#else return perf_singlethreaded ? 0 : pthread_rwlock_rdlock(&sem->lock); +#endif } int up_read(struct rw_semaphore *sem) { +#if RWS_ERRORCHECK + mutex_unlock(&sem->mtx); + return 0; +#else return perf_singlethreaded ? 0 : pthread_rwlock_unlock(&sem->lock); +#endif } int down_write(struct rw_semaphore *sem) { +#if RWS_ERRORCHECK + mutex_lock(&sem->mtx); + return 0; +#else return perf_singlethreaded ? 0 : pthread_rwlock_wrlock(&sem->lock); +#endif } int up_write(struct rw_semaphore *sem) { +#if RWS_ERRORCHECK + mutex_unlock(&sem->mtx); + return 0; +#else return perf_singlethreaded ? 0 : pthread_rwlock_unlock(&sem->lock); +#endif } diff --git a/tools/perf/util/rwsem.h b/tools/perf/util/rwsem.h index 94565ad4d494..ef5cbc31d967 100644 --- a/tools/perf/util/rwsem.h +++ b/tools/perf/util/rwsem.h @@ -2,9 +2,20 @@ #define _PERF_RWSEM_H #include +#include "mutex.h" + +/* + * Mutexes have additional error checking. Enable to use a mutex rather than a + * rwlock for debugging. + */ +#define RWS_ERRORCHECK 0 struct rw_semaphore { +#if RWS_ERRORCHECK + struct mutex mtx; +#else pthread_rwlock_t lock; +#endif }; int init_rwsem(struct rw_semaphore *sem); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 6aa1c7f2b444..80e4f6132740 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -128,7 +128,7 @@ static int hist_entry__thread_filter(struct hist_entry *he, int type, const void if (type != HIST_FILTER__THREAD) return -1; - return th && RC_CHK_ACCESS(he->thread) != RC_CHK_ACCESS(th); + return th && !RC_CHK_EQUAL(he->thread, th); } struct sort_entry sort_thread = { diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index cf05b0b56c57..116a642ad99d 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -301,3 +301,51 @@ unsigned int hex(char c) return c - 'a' + 10; return c - 'A' + 10; } + +/* + * Replace all occurrences of character 'needle' in string 'haystack' with + * string 'replace' + * + * The new string could be longer so a new string is returned which must be + * freed. + */ +char *strreplace_chars(char needle, const char *haystack, const char *replace) +{ + int replace_len = strlen(replace); + char *new_s, *to; + const char *loc = strchr(haystack, needle); + const char *from = haystack; + int num = 0; + + /* Count occurrences */ + while (loc) { + loc = strchr(loc + 1, needle); + num++; + } + + /* Allocate enough space for replacements and reset first location */ + new_s = malloc(strlen(haystack) + (num * (replace_len - 1) + 1)); + if (!new_s) + return NULL; + loc = strchr(haystack, needle); + to = new_s; + + while (loc) { + /* Copy original string up to found char and update positions */ + memcpy(to, from, 1 + loc - from); + to += loc - from; + from = loc + 1; + + /* Copy replacement string and update positions */ + memcpy(to, replace, replace_len); + to += replace_len; + + /* needle next occurrence or end of string */ + loc = strchr(from, needle); + } + + /* Copy any remaining chars + null */ + strcpy(to, from); + + return new_s; +} diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h index 56c30fef9682..52cb8ba057c7 100644 --- a/tools/perf/util/string2.h +++ b/tools/perf/util/string2.h @@ -39,5 +39,6 @@ char *strpbrk_esc(char *str, const char *stopset); char *strdup_esc(const char *str); unsigned int hex(char c); +char *strreplace_chars(char needle, const char *haystack, const char *replace); #endif /* PERF_STRING_H */ diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 0e4dc31c6c9c..1892e9b6aa7f 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c @@ -754,6 +754,7 @@ int svg_build_topology_map(struct perf_env *env) int i, nr_cpus; struct topology t; char *sib_core, *sib_thr; + int ret = -1; nr_cpus = min(env->nr_cpus_online, MAX_NR_CPUS); @@ -799,11 +800,11 @@ int svg_build_topology_map(struct perf_env *env) scan_core_topology(topology_map, &t, nr_cpus); - return 0; + ret = 0; exit: zfree(&t.sib_core); zfree(&t.sib_thr); - return -1; + return ret; } diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 95e99c332d7e..9e7eeaf616b8 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1514,8 +1514,10 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, } if (elf_section_by_name(runtime_ss->elf, &runtime_ss->ehdr, &tshdr, - ".text", NULL)) + ".text", NULL)) { dso->text_offset = tshdr.sh_addr - tshdr.sh_offset; + dso->text_end = tshdr.sh_offset + tshdr.sh_size; + } if (runtime_ss->opdsec) opddata = elf_rawdata(runtime_ss->opdsec, NULL); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3f36675b7c8f..82cc74b9358e 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -202,11 +202,10 @@ void symbols__fixup_duplicate(struct rb_root_cached *symbols) curr = rb_entry(nd, struct symbol, rb_node); again: nd = rb_next(&curr->rb_node); - next = rb_entry(nd, struct symbol, rb_node); - if (!nd) break; + next = rb_entry(nd, struct symbol, rb_node); if (curr->start != next->start) continue; @@ -719,6 +718,7 @@ static bool symbol__is_idle(const char *name) "cpu_startup_entry", "idle_cpu", "intel_idle", + "intel_idle_ibrs", "default_idle", "native_safe_halt", "enter_idle", @@ -877,7 +877,7 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta, *module++ = '\0'; curr_map_dso = map__dso(curr_map); if (strcmp(curr_map_dso->short_name, module)) { - if (RC_CHK_ACCESS(curr_map) != RC_CHK_ACCESS(initial_map) && + if (!RC_CHK_EQUAL(curr_map, initial_map) && dso->kernel == DSO_SPACE__KERNEL_GUEST && machine__is_default_guest(machine)) { /* @@ -1469,7 +1469,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, list_del_init(&new_node->node); - if (RC_CHK_ACCESS(new_map) == RC_CHK_ACCESS(replacement_map)) { + if (RC_CHK_EQUAL(new_map, replacement_map)) { struct map *map_ref; map__set_start(map, map__start(new_map)); @@ -1733,8 +1733,10 @@ int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) /* PE symbols can only have 4 bytes, so use .text high bits */ dso->text_offset = section->vma - (u32)section->vma; dso->text_offset += (u32)bfd_asymbol_value(symbols[i]); + dso->text_end = (section->vma - dso->text_offset) + section->size; } else { dso->text_offset = section->vma - section->filepos; + dso->text_end = section->filepos + section->size; } } @@ -2789,8 +2791,11 @@ struct mem_info *mem_info__get(struct mem_info *mi) void mem_info__put(struct mem_info *mi) { - if (mi && refcount_dec_and_test(&mi->refcnt)) + if (mi && refcount_dec_and_test(&mi->refcnt)) { + addr_map_symbol__exit(&mi->iaddr); + addr_map_symbol__exit(&mi->daddr); free(mi); + } } struct mem_info *mem_info__new(void) diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 319ccf09a435..c8755679281e 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -313,7 +313,8 @@ static int record_event_files(struct tracepoint_path *tps) } err = 0; out: - closedir(dir); + if (dir) + closedir(dir); put_tracing_file(path); return err; diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index ff527ac065cf..6fba29f3222d 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -136,7 +136,15 @@ else NO_SUBDIR = : endif -ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) +# If the user is running make -s (silent mode), suppress echoing of commands +# make-4.0 (and later) keep single letter options in the 1st word of MAKEFLAGS. +ifeq ($(filter 3.%,$(MAKE_VERSION)),) +short-opts := $(firstword -$(MAKEFLAGS)) +else +short-opts := $(filter-out --%,$(MAKEFLAGS)) +endif + +ifneq ($(findstring s,$(short-opts)),) silent=1 endif diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc index 21db6b720754..e21c9c27ece4 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc @@ -40,7 +40,9 @@ riscv*) esac : "Test get argument (1)" -if grep -q eventfs_add_dir available_filter_functions; then +if grep -q eventfs_create_dir available_filter_functions; then + DIR_NAME="eventfs_create_dir" +elif grep -q eventfs_add_dir available_filter_functions; then DIR_NAME="eventfs_add_dir" else DIR_NAME="tracefs_create_dir" diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc index 4e086f871cee..93217d459556 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc @@ -40,7 +40,9 @@ riscv*) esac : "Test get argument (1)" -if grep -q eventfs_add_dir available_filter_functions; then +if grep -q eventfs_create_dir available_filter_functions; then + DIR_NAME="eventfs_create_dir" +elif grep -q eventfs_add_dir available_filter_functions; then DIR_NAME="eventfs_add_dir" else DIR_NAME="tracefs_create_dir" diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c index 792c3f0a59b4..646f778dfb1e 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -75,7 +75,7 @@ TEST(abi_version) const struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE, }; - ASSERT_EQ(3, landlock_create_ruleset(NULL, 0, + ASSERT_EQ(4, landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION)); ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, diff --git a/tools/testing/selftests/landlock/common.h b/tools/testing/selftests/landlock/common.h index d7987ae8d7fc..5b79758cae62 100644 --- a/tools/testing/selftests/landlock/common.h +++ b/tools/testing/selftests/landlock/common.h @@ -112,10 +112,13 @@ static void _init_caps(struct __test_metadata *const _metadata, bool drop_all) cap_t cap_p; /* Only these three capabilities are useful for the tests. */ const cap_value_t caps[] = { + /* clang-format off */ CAP_DAC_OVERRIDE, CAP_MKNOD, CAP_SYS_ADMIN, CAP_SYS_CHROOT, + CAP_NET_BIND_SERVICE, + /* clang-format on */ }; cap_p = cap_get_proc(); @@ -256,3 +259,13 @@ static int __maybe_unused send_fd(int usock, int fd_tx) return -errno; return 0; } + +static void __maybe_unused +enforce_ruleset(struct __test_metadata *const _metadata, const int ruleset_fd) +{ + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); + ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)) + { + TH_LOG("Failed to enforce ruleset: %s", strerror(errno)); + } +} diff --git a/tools/testing/selftests/landlock/config b/tools/testing/selftests/landlock/config index 3dc9e438eab1..0086efaa7b68 100644 --- a/tools/testing/selftests/landlock/config +++ b/tools/testing/selftests/landlock/config @@ -1,5 +1,9 @@ CONFIG_CGROUPS=y CONFIG_CGROUP_SCHED=y +CONFIG_INET=y +CONFIG_IPV6=y +CONFIG_NET=y +CONFIG_NET_NS=y CONFIG_OVERLAY_FS=y CONFIG_PROC_FS=y CONFIG_SECURITY=y diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 251594306d40..18e1f86a6234 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -677,16 +677,6 @@ static int create_ruleset(struct __test_metadata *const _metadata, return ruleset_fd; } -static void enforce_ruleset(struct __test_metadata *const _metadata, - const int ruleset_fd) -{ - ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); - ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)) - { - TH_LOG("Failed to enforce ruleset: %s", strerror(errno)); - } -} - TEST_F_FORK(layout0, proc_nsfs) { const struct rule rules[] = { @@ -1635,6 +1625,65 @@ TEST_F_FORK(layout1, move_mount) clear_cap(_metadata, CAP_SYS_ADMIN); } +TEST_F_FORK(layout1, topology_changes_with_net_only) +{ + const struct landlock_ruleset_attr ruleset_net = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + int ruleset_fd; + + /* Add network restrictions. */ + ruleset_fd = + landlock_create_ruleset(&ruleset_net, sizeof(ruleset_net), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Mount, remount, move_mount, umount, and pivot_root checks. */ + set_cap(_metadata, CAP_SYS_ADMIN); + ASSERT_EQ(0, mount_opt(&mnt_tmp, dir_s1d2)); + ASSERT_EQ(0, mount(NULL, dir_s1d2, NULL, MS_PRIVATE | MS_REC, NULL)); + ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD, + dir_s2d2, 0)); + ASSERT_EQ(0, umount(dir_s2d2)); + ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3)); + ASSERT_EQ(0, chdir("/")); + clear_cap(_metadata, CAP_SYS_ADMIN); +} + +TEST_F_FORK(layout1, topology_changes_with_net_and_fs) +{ + const struct landlock_ruleset_attr ruleset_net_fs = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE, + }; + int ruleset_fd; + + /* Add network and filesystem restrictions. */ + ruleset_fd = landlock_create_ruleset(&ruleset_net_fs, + sizeof(ruleset_net_fs), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* Mount, remount, move_mount, umount, and pivot_root checks. */ + set_cap(_metadata, CAP_SYS_ADMIN); + ASSERT_EQ(-1, mount_opt(&mnt_tmp, dir_s1d2)); + ASSERT_EQ(EPERM, errno); + ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_PRIVATE | MS_REC, NULL)); + ASSERT_EQ(EPERM, errno); + ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD, + dir_s2d2, 0)); + ASSERT_EQ(EPERM, errno); + ASSERT_EQ(-1, umount(dir_s3d2)); + ASSERT_EQ(EPERM, errno); + ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3)); + ASSERT_EQ(EPERM, errno); + clear_cap(_metadata, CAP_SYS_ADMIN); +} + TEST_F_FORK(layout1, release_inodes) { const struct rule rules[] = { diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c new file mode 100644 index 000000000000..929e21c4db05 --- /dev/null +++ b/tools/testing/selftests/landlock/net_test.c @@ -0,0 +1,1738 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Landlock tests - Network + * + * Copyright © 2022-2023 Huawei Tech. Co., Ltd. + * Copyright © 2023 Microsoft Corporation + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +const short sock_port_start = (1 << 10); + +static const char loopback_ipv4[] = "127.0.0.1"; +static const char loopback_ipv6[] = "::1"; + +/* Number pending connections queue to be hold. */ +const short backlog = 10; + +enum sandbox_type { + NO_SANDBOX, + /* This may be used to test rules that allow *and* deny accesses. */ + TCP_SANDBOX, +}; + +struct protocol_variant { + int domain; + int type; +}; + +struct service_fixture { + struct protocol_variant protocol; + /* port is also stored in ipv4_addr.sin_port or ipv6_addr.sin6_port */ + unsigned short port; + union { + struct sockaddr_in ipv4_addr; + struct sockaddr_in6 ipv6_addr; + struct { + struct sockaddr_un unix_addr; + socklen_t unix_addr_len; + }; + }; +}; + +static int set_service(struct service_fixture *const srv, + const struct protocol_variant prot, + const unsigned short index) +{ + memset(srv, 0, sizeof(*srv)); + + /* + * Copies all protocol properties in case of the variant only contains + * a subset of them. + */ + srv->protocol = prot; + + /* Checks for port overflow. */ + if (index > 2) + return 1; + srv->port = sock_port_start << (2 * index); + + switch (prot.domain) { + case AF_UNSPEC: + case AF_INET: + srv->ipv4_addr.sin_family = prot.domain; + srv->ipv4_addr.sin_port = htons(srv->port); + srv->ipv4_addr.sin_addr.s_addr = inet_addr(loopback_ipv4); + return 0; + + case AF_INET6: + srv->ipv6_addr.sin6_family = prot.domain; + srv->ipv6_addr.sin6_port = htons(srv->port); + inet_pton(AF_INET6, loopback_ipv6, &srv->ipv6_addr.sin6_addr); + return 0; + + case AF_UNIX: + srv->unix_addr.sun_family = prot.domain; + sprintf(srv->unix_addr.sun_path, + "_selftests-landlock-net-tid%d-index%d", gettid(), + index); + srv->unix_addr_len = SUN_LEN(&srv->unix_addr); + srv->unix_addr.sun_path[0] = '\0'; + return 0; + } + return 1; +} + +static void setup_loopback(struct __test_metadata *const _metadata) +{ + set_cap(_metadata, CAP_SYS_ADMIN); + ASSERT_EQ(0, unshare(CLONE_NEWNET)); + ASSERT_EQ(0, system("ip link set dev lo up")); + clear_cap(_metadata, CAP_SYS_ADMIN); +} + +static bool is_restricted(const struct protocol_variant *const prot, + const enum sandbox_type sandbox) +{ + switch (prot->domain) { + case AF_INET: + case AF_INET6: + switch (prot->type) { + case SOCK_STREAM: + return sandbox == TCP_SANDBOX; + } + break; + } + return false; +} + +static int socket_variant(const struct service_fixture *const srv) +{ + int ret; + + ret = socket(srv->protocol.domain, srv->protocol.type | SOCK_CLOEXEC, + 0); + if (ret < 0) + return -errno; + return ret; +} + +#ifndef SIN6_LEN_RFC2133 +#define SIN6_LEN_RFC2133 24 +#endif + +static socklen_t get_addrlen(const struct service_fixture *const srv, + const bool minimal) +{ + switch (srv->protocol.domain) { + case AF_UNSPEC: + case AF_INET: + return sizeof(srv->ipv4_addr); + + case AF_INET6: + if (minimal) + return SIN6_LEN_RFC2133; + return sizeof(srv->ipv6_addr); + + case AF_UNIX: + if (minimal) + return sizeof(srv->unix_addr) - + sizeof(srv->unix_addr.sun_path); + return srv->unix_addr_len; + + default: + return 0; + } +} + +static void set_port(struct service_fixture *const srv, uint16_t port) +{ + switch (srv->protocol.domain) { + case AF_UNSPEC: + case AF_INET: + srv->ipv4_addr.sin_port = htons(port); + return; + + case AF_INET6: + srv->ipv6_addr.sin6_port = htons(port); + return; + + default: + return; + } +} + +static uint16_t get_binded_port(int socket_fd, + const struct protocol_variant *const prot) +{ + struct sockaddr_in ipv4_addr; + struct sockaddr_in6 ipv6_addr; + socklen_t ipv4_addr_len, ipv6_addr_len; + + /* Gets binded port. */ + switch (prot->domain) { + case AF_UNSPEC: + case AF_INET: + ipv4_addr_len = sizeof(ipv4_addr); + getsockname(socket_fd, &ipv4_addr, &ipv4_addr_len); + return ntohs(ipv4_addr.sin_port); + + case AF_INET6: + ipv6_addr_len = sizeof(ipv6_addr); + getsockname(socket_fd, &ipv6_addr, &ipv6_addr_len); + return ntohs(ipv6_addr.sin6_port); + + default: + return 0; + } +} + +static int bind_variant_addrlen(const int sock_fd, + const struct service_fixture *const srv, + const socklen_t addrlen) +{ + int ret; + + switch (srv->protocol.domain) { + case AF_UNSPEC: + case AF_INET: + ret = bind(sock_fd, &srv->ipv4_addr, addrlen); + break; + + case AF_INET6: + ret = bind(sock_fd, &srv->ipv6_addr, addrlen); + break; + + case AF_UNIX: + ret = bind(sock_fd, &srv->unix_addr, addrlen); + break; + + default: + errno = EAFNOSUPPORT; + return -errno; + } + + if (ret < 0) + return -errno; + return ret; +} + +static int bind_variant(const int sock_fd, + const struct service_fixture *const srv) +{ + return bind_variant_addrlen(sock_fd, srv, get_addrlen(srv, false)); +} + +static int connect_variant_addrlen(const int sock_fd, + const struct service_fixture *const srv, + const socklen_t addrlen) +{ + int ret; + + switch (srv->protocol.domain) { + case AF_UNSPEC: + case AF_INET: + ret = connect(sock_fd, &srv->ipv4_addr, addrlen); + break; + + case AF_INET6: + ret = connect(sock_fd, &srv->ipv6_addr, addrlen); + break; + + case AF_UNIX: + ret = connect(sock_fd, &srv->unix_addr, addrlen); + break; + + default: + errno = -EAFNOSUPPORT; + return -errno; + } + + if (ret < 0) + return -errno; + return ret; +} + +static int connect_variant(const int sock_fd, + const struct service_fixture *const srv) +{ + return connect_variant_addrlen(sock_fd, srv, get_addrlen(srv, false)); +} + +FIXTURE(protocol) +{ + struct service_fixture srv0, srv1, srv2, unspec_any0, unspec_srv0; +}; + +FIXTURE_VARIANT(protocol) +{ + const enum sandbox_type sandbox; + const struct protocol_variant prot; +}; + +FIXTURE_SETUP(protocol) +{ + const struct protocol_variant prot_unspec = { + .domain = AF_UNSPEC, + .type = SOCK_STREAM, + }; + + disable_caps(_metadata); + + ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0)); + ASSERT_EQ(0, set_service(&self->srv1, variant->prot, 1)); + ASSERT_EQ(0, set_service(&self->srv2, variant->prot, 2)); + + ASSERT_EQ(0, set_service(&self->unspec_srv0, prot_unspec, 0)); + + ASSERT_EQ(0, set_service(&self->unspec_any0, prot_unspec, 0)); + self->unspec_any0.ipv4_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(protocol) +{ +} + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_tcp) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_INET, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_tcp) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_INET6, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv4_udp) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_INET, + .type = SOCK_DGRAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_ipv6_udp) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_INET6, + .type = SOCK_DGRAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_unix_stream) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_UNIX, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, no_sandbox_with_unix_datagram) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_UNIX, + .type = SOCK_DGRAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_tcp) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_INET, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_tcp) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_INET6, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv4_udp) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_INET, + .type = SOCK_DGRAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_ipv6_udp) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_INET6, + .type = SOCK_DGRAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_stream) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_UNIX, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(protocol, tcp_sandbox_with_unix_datagram) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_UNIX, + .type = SOCK_DGRAM, + }, +}; + +static void test_bind_and_connect(struct __test_metadata *const _metadata, + const struct service_fixture *const srv, + const bool deny_bind, const bool deny_connect) +{ + char buf = '\0'; + int inval_fd, bind_fd, client_fd, status, ret; + pid_t child; + + /* Starts invalid addrlen tests with bind. */ + inval_fd = socket_variant(srv); + ASSERT_LE(0, inval_fd) + { + TH_LOG("Failed to create socket: %s", strerror(errno)); + } + + /* Tries to bind with zero as addrlen. */ + EXPECT_EQ(-EINVAL, bind_variant_addrlen(inval_fd, srv, 0)); + + /* Tries to bind with too small addrlen. */ + EXPECT_EQ(-EINVAL, bind_variant_addrlen(inval_fd, srv, + get_addrlen(srv, true) - 1)); + + /* Tries to bind with minimal addrlen. */ + ret = bind_variant_addrlen(inval_fd, srv, get_addrlen(srv, true)); + if (deny_bind) { + EXPECT_EQ(-EACCES, ret); + } else { + EXPECT_EQ(0, ret) + { + TH_LOG("Failed to bind to socket: %s", strerror(errno)); + } + } + EXPECT_EQ(0, close(inval_fd)); + + /* Starts invalid addrlen tests with connect. */ + inval_fd = socket_variant(srv); + ASSERT_LE(0, inval_fd); + + /* Tries to connect with zero as addrlen. */ + EXPECT_EQ(-EINVAL, connect_variant_addrlen(inval_fd, srv, 0)); + + /* Tries to connect with too small addrlen. */ + EXPECT_EQ(-EINVAL, connect_variant_addrlen(inval_fd, srv, + get_addrlen(srv, true) - 1)); + + /* Tries to connect with minimal addrlen. */ + ret = connect_variant_addrlen(inval_fd, srv, get_addrlen(srv, true)); + if (srv->protocol.domain == AF_UNIX) { + EXPECT_EQ(-EINVAL, ret); + } else if (deny_connect) { + EXPECT_EQ(-EACCES, ret); + } else if (srv->protocol.type == SOCK_STREAM) { + /* No listening server, whatever the value of deny_bind. */ + EXPECT_EQ(-ECONNREFUSED, ret); + } else { + EXPECT_EQ(0, ret) + { + TH_LOG("Failed to connect to socket: %s", + strerror(errno)); + } + } + EXPECT_EQ(0, close(inval_fd)); + + /* Starts connection tests. */ + bind_fd = socket_variant(srv); + ASSERT_LE(0, bind_fd); + + ret = bind_variant(bind_fd, srv); + if (deny_bind) { + EXPECT_EQ(-EACCES, ret); + } else { + EXPECT_EQ(0, ret); + + /* Creates a listening socket. */ + if (srv->protocol.type == SOCK_STREAM) + EXPECT_EQ(0, listen(bind_fd, backlog)); + } + + child = fork(); + ASSERT_LE(0, child); + if (child == 0) { + int connect_fd, ret; + + /* Closes listening socket for the child. */ + EXPECT_EQ(0, close(bind_fd)); + + /* Starts connection tests. */ + connect_fd = socket_variant(srv); + ASSERT_LE(0, connect_fd); + ret = connect_variant(connect_fd, srv); + if (deny_connect) { + EXPECT_EQ(-EACCES, ret); + } else if (deny_bind) { + /* No listening server. */ + EXPECT_EQ(-ECONNREFUSED, ret); + } else { + EXPECT_EQ(0, ret); + EXPECT_EQ(1, write(connect_fd, ".", 1)); + } + + EXPECT_EQ(0, close(connect_fd)); + _exit(_metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE); + return; + } + + /* Accepts connection from the child. */ + client_fd = bind_fd; + if (!deny_bind && !deny_connect) { + if (srv->protocol.type == SOCK_STREAM) { + client_fd = accept(bind_fd, NULL, 0); + ASSERT_LE(0, client_fd); + } + + EXPECT_EQ(1, read(client_fd, &buf, 1)); + EXPECT_EQ('.', buf); + } + + EXPECT_EQ(child, waitpid(child, &status, 0)); + EXPECT_EQ(1, WIFEXITED(status)); + EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + /* Closes connection, if any. */ + if (client_fd != bind_fd) + EXPECT_LE(0, close(client_fd)); + + /* Closes listening socket. */ + EXPECT_EQ(0, close(bind_fd)); +} + +TEST_F(protocol, bind) +{ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr tcp_bind_connect_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv0.port, + }; + const struct landlock_net_port_attr tcp_connect_p1 = { + .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv1.port, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows connect and bind for the first port. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect_p0, 0)); + + /* Allows connect and denies bind for the second port. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_connect_p1, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + /* Binds a socket to the first port. */ + test_bind_and_connect(_metadata, &self->srv0, false, false); + + /* Binds a socket to the second port. */ + test_bind_and_connect(_metadata, &self->srv1, + is_restricted(&variant->prot, variant->sandbox), + false); + + /* Binds a socket to the third port. */ + test_bind_and_connect(_metadata, &self->srv2, + is_restricted(&variant->prot, variant->sandbox), + is_restricted(&variant->prot, variant->sandbox)); +} + +TEST_F(protocol, connect) +{ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr tcp_bind_connect_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv0.port, + }; + const struct landlock_net_port_attr tcp_bind_p1 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv1.port, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows connect and bind for the first port. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect_p0, 0)); + + /* Allows bind and denies connect for the second port. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_p1, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + test_bind_and_connect(_metadata, &self->srv0, false, false); + + test_bind_and_connect(_metadata, &self->srv1, false, + is_restricted(&variant->prot, variant->sandbox)); + + test_bind_and_connect(_metadata, &self->srv2, + is_restricted(&variant->prot, variant->sandbox), + is_restricted(&variant->prot, variant->sandbox)); +} + +TEST_F(protocol, bind_unspec) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, + }; + const struct landlock_net_port_attr tcp_bind = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv0.port, + }; + int bind_fd, ret; + + if (variant->sandbox == TCP_SANDBOX) { + const int ruleset_fd = landlock_create_ruleset( + &ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows bind. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + + /* Allowed bind on AF_UNSPEC/INADDR_ANY. */ + ret = bind_variant(bind_fd, &self->unspec_any0); + if (variant->prot.domain == AF_INET) { + EXPECT_EQ(0, ret) + { + TH_LOG("Failed to bind to unspec/any socket: %s", + strerror(errno)); + } + } else { + EXPECT_EQ(-EINVAL, ret); + } + EXPECT_EQ(0, close(bind_fd)); + + if (variant->sandbox == TCP_SANDBOX) { + const int ruleset_fd = landlock_create_ruleset( + &ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Denies bind. */ + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + + /* Denied bind on AF_UNSPEC/INADDR_ANY. */ + ret = bind_variant(bind_fd, &self->unspec_any0); + if (variant->prot.domain == AF_INET) { + if (is_restricted(&variant->prot, variant->sandbox)) { + EXPECT_EQ(-EACCES, ret); + } else { + EXPECT_EQ(0, ret); + } + } else { + EXPECT_EQ(-EINVAL, ret); + } + EXPECT_EQ(0, close(bind_fd)); + + /* Checks bind with AF_UNSPEC and the loopback address. */ + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + ret = bind_variant(bind_fd, &self->unspec_srv0); + if (variant->prot.domain == AF_INET) { + EXPECT_EQ(-EAFNOSUPPORT, ret); + } else { + EXPECT_EQ(-EINVAL, ret) + { + TH_LOG("Wrong bind error: %s", strerror(errno)); + } + } + EXPECT_EQ(0, close(bind_fd)); +} + +TEST_F(protocol, connect_unspec) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr tcp_connect = { + .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv0.port, + }; + int bind_fd, client_fd, status; + pid_t child; + + /* Specific connection tests. */ + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0)); + if (self->srv0.protocol.type == SOCK_STREAM) + EXPECT_EQ(0, listen(bind_fd, backlog)); + + child = fork(); + ASSERT_LE(0, child); + if (child == 0) { + int connect_fd, ret; + + /* Closes listening socket for the child. */ + EXPECT_EQ(0, close(bind_fd)); + + connect_fd = socket_variant(&self->srv0); + ASSERT_LE(0, connect_fd); + EXPECT_EQ(0, connect_variant(connect_fd, &self->srv0)); + + /* Tries to connect again, or set peer. */ + ret = connect_variant(connect_fd, &self->srv0); + if (self->srv0.protocol.type == SOCK_STREAM) { + EXPECT_EQ(-EISCONN, ret); + } else { + EXPECT_EQ(0, ret); + } + + if (variant->sandbox == TCP_SANDBOX) { + const int ruleset_fd = landlock_create_ruleset( + &ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows connect. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, + LANDLOCK_RULE_NET_PORT, + &tcp_connect, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + /* Disconnects already connected socket, or set peer. */ + ret = connect_variant(connect_fd, &self->unspec_any0); + if (self->srv0.protocol.domain == AF_UNIX && + self->srv0.protocol.type == SOCK_STREAM) { + EXPECT_EQ(-EINVAL, ret); + } else { + EXPECT_EQ(0, ret); + } + + /* Tries to reconnect, or set peer. */ + ret = connect_variant(connect_fd, &self->srv0); + if (self->srv0.protocol.domain == AF_UNIX && + self->srv0.protocol.type == SOCK_STREAM) { + EXPECT_EQ(-EISCONN, ret); + } else { + EXPECT_EQ(0, ret); + } + + if (variant->sandbox == TCP_SANDBOX) { + const int ruleset_fd = landlock_create_ruleset( + &ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Denies connect. */ + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + ret = connect_variant(connect_fd, &self->unspec_any0); + if (self->srv0.protocol.domain == AF_UNIX && + self->srv0.protocol.type == SOCK_STREAM) { + EXPECT_EQ(-EINVAL, ret); + } else { + /* Always allowed to disconnect. */ + EXPECT_EQ(0, ret); + } + + EXPECT_EQ(0, close(connect_fd)); + _exit(_metadata->passed ? EXIT_SUCCESS : EXIT_FAILURE); + return; + } + + client_fd = bind_fd; + if (self->srv0.protocol.type == SOCK_STREAM) { + client_fd = accept(bind_fd, NULL, 0); + ASSERT_LE(0, client_fd); + } + + EXPECT_EQ(child, waitpid(child, &status, 0)); + EXPECT_EQ(1, WIFEXITED(status)); + EXPECT_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + /* Closes connection, if any. */ + if (client_fd != bind_fd) + EXPECT_LE(0, close(client_fd)); + + /* Closes listening socket. */ + EXPECT_EQ(0, close(bind_fd)); +} + +FIXTURE(ipv4) +{ + struct service_fixture srv0, srv1; +}; + +FIXTURE_VARIANT(ipv4) +{ + const enum sandbox_type sandbox; + const int type; +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ipv4, no_sandbox_with_tcp) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .type = SOCK_STREAM, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ipv4, tcp_sandbox_with_tcp) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .type = SOCK_STREAM, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ipv4, no_sandbox_with_udp) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .type = SOCK_DGRAM, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ipv4, tcp_sandbox_with_udp) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .type = SOCK_DGRAM, +}; + +FIXTURE_SETUP(ipv4) +{ + const struct protocol_variant prot = { + .domain = AF_INET, + .type = variant->type, + }; + + disable_caps(_metadata); + + set_service(&self->srv0, prot, 0); + set_service(&self->srv1, prot, 1); + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(ipv4) +{ +} + +TEST_F(ipv4, from_unix_to_inet) +{ + int unix_stream_fd, unix_dgram_fd; + + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr tcp_bind_connect_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv0.port, + }; + int ruleset_fd; + + /* Denies connect and bind to check errno value. */ + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows connect and bind for srv0. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect_p0, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + unix_stream_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + ASSERT_LE(0, unix_stream_fd); + + unix_dgram_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + ASSERT_LE(0, unix_dgram_fd); + + /* Checks unix stream bind and connect for srv0. */ + EXPECT_EQ(-EINVAL, bind_variant(unix_stream_fd, &self->srv0)); + EXPECT_EQ(-EINVAL, connect_variant(unix_stream_fd, &self->srv0)); + + /* Checks unix stream bind and connect for srv1. */ + EXPECT_EQ(-EINVAL, bind_variant(unix_stream_fd, &self->srv1)) + { + TH_LOG("Wrong bind error: %s", strerror(errno)); + } + EXPECT_EQ(-EINVAL, connect_variant(unix_stream_fd, &self->srv1)); + + /* Checks unix datagram bind and connect for srv0. */ + EXPECT_EQ(-EINVAL, bind_variant(unix_dgram_fd, &self->srv0)); + EXPECT_EQ(-EINVAL, connect_variant(unix_dgram_fd, &self->srv0)); + + /* Checks unix datagram bind and connect for srv1. */ + EXPECT_EQ(-EINVAL, bind_variant(unix_dgram_fd, &self->srv1)); + EXPECT_EQ(-EINVAL, connect_variant(unix_dgram_fd, &self->srv1)); +} + +FIXTURE(tcp_layers) +{ + struct service_fixture srv0, srv1; +}; + +FIXTURE_VARIANT(tcp_layers) +{ + const size_t num_layers; + const int domain; +}; + +FIXTURE_SETUP(tcp_layers) +{ + const struct protocol_variant prot = { + .domain = variant->domain, + .type = SOCK_STREAM, + }; + + disable_caps(_metadata); + + ASSERT_EQ(0, set_service(&self->srv0, prot, 0)); + ASSERT_EQ(0, set_service(&self->srv1, prot, 1)); + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(tcp_layers) +{ +} + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, no_sandbox_with_ipv4) { + /* clang-format on */ + .domain = AF_INET, + .num_layers = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, one_sandbox_with_ipv4) { + /* clang-format on */ + .domain = AF_INET, + .num_layers = 1, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, two_sandboxes_with_ipv4) { + /* clang-format on */ + .domain = AF_INET, + .num_layers = 2, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, three_sandboxes_with_ipv4) { + /* clang-format on */ + .domain = AF_INET, + .num_layers = 3, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, no_sandbox_with_ipv6) { + /* clang-format on */ + .domain = AF_INET6, + .num_layers = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, one_sandbox_with_ipv6) { + /* clang-format on */ + .domain = AF_INET6, + .num_layers = 1, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, two_sandboxes_with_ipv6) { + /* clang-format on */ + .domain = AF_INET6, + .num_layers = 2, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(tcp_layers, three_sandboxes_with_ipv6) { + /* clang-format on */ + .domain = AF_INET6, + .num_layers = 3, +}; + +TEST_F(tcp_layers, ruleset_overlap) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr tcp_bind = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv0.port, + }; + const struct landlock_net_port_attr tcp_bind_connect = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv0.port, + }; + + if (variant->num_layers >= 1) { + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Allows bind. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind, 0)); + /* Also allows bind, but allows connect too. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + if (variant->num_layers >= 2) { + int ruleset_fd; + + /* Creates another ruleset layer. */ + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Only allows bind. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + if (variant->num_layers >= 3) { + int ruleset_fd; + + /* Creates another ruleset layer. */ + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Try to allow bind and connect. */ + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + /* + * Forbids to connect to the socket because only one ruleset layer + * allows connect. + */ + test_bind_and_connect(_metadata, &self->srv0, false, + variant->num_layers >= 2); +} + +TEST_F(tcp_layers, ruleset_expand) +{ + if (variant->num_layers >= 1) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, + }; + /* Allows bind for srv0. */ + const struct landlock_net_port_attr bind_srv0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv0.port, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &bind_srv0, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + if (variant->num_layers >= 2) { + /* Expands network mask with connect action. */ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + /* Allows bind for srv0 and connect to srv0. */ + const struct landlock_net_port_attr tcp_bind_connect_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = self->srv0.port, + }; + /* Try to allow bind for srv1. */ + const struct landlock_net_port_attr tcp_bind_p1 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv1.port, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect_p0, 0)); + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_p1, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + if (variant->num_layers >= 3) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + /* Allows connect to srv0, without bind rule. */ + const struct landlock_net_port_attr tcp_bind_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv0.port, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_p0, 0)); + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + test_bind_and_connect(_metadata, &self->srv0, false, + variant->num_layers >= 3); + + test_bind_and_connect(_metadata, &self->srv1, variant->num_layers >= 1, + variant->num_layers >= 2); +} + +/* clang-format off */ +FIXTURE(mini) {}; +/* clang-format on */ + +FIXTURE_SETUP(mini) +{ + disable_caps(_metadata); + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(mini) +{ +} + +/* clang-format off */ + +#define ACCESS_LAST LANDLOCK_ACCESS_NET_CONNECT_TCP + +#define ACCESS_ALL ( \ + LANDLOCK_ACCESS_NET_BIND_TCP | \ + LANDLOCK_ACCESS_NET_CONNECT_TCP) + +/* clang-format on */ + +TEST_F(mini, network_access_rights) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = ACCESS_ALL, + }; + struct landlock_net_port_attr net_port = { + .port = sock_port_start, + }; + int ruleset_fd; + __u64 access; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + for (access = 1; access <= ACCESS_LAST; access <<= 1) { + net_port.allowed_access = access; + EXPECT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &net_port, 0)) + { + TH_LOG("Failed to add rule with access 0x%llx: %s", + access, strerror(errno)); + } + } + EXPECT_EQ(0, close(ruleset_fd)); +} + +/* Checks invalid attribute, out of landlock network access range. */ +TEST_F(mini, unknown_access_rights) +{ + __u64 access_mask; + + for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST; + access_mask >>= 1) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = access_mask, + }; + + EXPECT_EQ(-1, landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0)); + EXPECT_EQ(EINVAL, errno); + } +} + +TEST_F(mini, inval) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP + }; + const struct landlock_net_port_attr tcp_bind_connect = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = sock_port_start, + }; + const struct landlock_net_port_attr tcp_denied = { + .allowed_access = 0, + .port = sock_port_start, + }; + const struct landlock_net_port_attr tcp_bind = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = sock_port_start, + }; + int ruleset_fd; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Checks unhandled allowed_access. */ + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect, 0)); + EXPECT_EQ(EINVAL, errno); + + /* Checks zero access value. */ + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_denied, 0)); + EXPECT_EQ(ENOMSG, errno); + + /* Adds with legitimate values. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind, 0)); +} + +TEST_F(mini, tcp_port_overflow) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr port_max_bind = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = UINT16_MAX, + }; + const struct landlock_net_port_attr port_max_connect = { + .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = UINT16_MAX, + }; + const struct landlock_net_port_attr port_overflow1 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = UINT16_MAX + 1, + }; + const struct landlock_net_port_attr port_overflow2 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = UINT16_MAX + 2, + }; + const struct landlock_net_port_attr port_overflow3 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = UINT32_MAX + 1UL, + }; + const struct landlock_net_port_attr port_overflow4 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = UINT32_MAX + 2UL, + }; + const struct protocol_variant ipv4_tcp = { + .domain = AF_INET, + .type = SOCK_STREAM, + }; + struct service_fixture srv_denied, srv_max_allowed; + int ruleset_fd; + + ASSERT_EQ(0, set_service(&srv_denied, ipv4_tcp, 0)); + + /* Be careful to avoid port inconsistencies. */ + srv_max_allowed = srv_denied; + srv_max_allowed.port = port_max_bind.port; + srv_max_allowed.ipv4_addr.sin_port = htons(port_max_bind.port); + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &port_max_bind, 0)); + + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &port_overflow1, 0)); + EXPECT_EQ(EINVAL, errno); + + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &port_overflow2, 0)); + EXPECT_EQ(EINVAL, errno); + + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &port_overflow3, 0)); + EXPECT_EQ(EINVAL, errno); + + /* Interleaves with invalid rule additions. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &port_max_connect, 0)); + + EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &port_overflow4, 0)); + EXPECT_EQ(EINVAL, errno); + + enforce_ruleset(_metadata, ruleset_fd); + + test_bind_and_connect(_metadata, &srv_denied, true, true); + test_bind_and_connect(_metadata, &srv_max_allowed, false, false); +} + +FIXTURE(ipv4_tcp) +{ + struct service_fixture srv0, srv1; +}; + +FIXTURE_SETUP(ipv4_tcp) +{ + const struct protocol_variant ipv4_tcp = { + .domain = AF_INET, + .type = SOCK_STREAM, + }; + + disable_caps(_metadata); + + ASSERT_EQ(0, set_service(&self->srv0, ipv4_tcp, 0)); + ASSERT_EQ(0, set_service(&self->srv1, ipv4_tcp, 1)); + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(ipv4_tcp) +{ +} + +TEST_F(ipv4_tcp, port_endianness) +{ + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + }; + const struct landlock_net_port_attr bind_host_endian_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + /* Host port format. */ + .port = self->srv0.port, + }; + const struct landlock_net_port_attr connect_big_endian_p0 = { + .allowed_access = LANDLOCK_ACCESS_NET_CONNECT_TCP, + /* Big endian port format. */ + .port = htons(self->srv0.port), + }; + const struct landlock_net_port_attr bind_connect_host_endian_p1 = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + /* Host port format. */ + .port = self->srv1.port, + }; + const unsigned int one = 1; + const char little_endian = *(const char *)&one; + int ruleset_fd; + + ruleset_fd = + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &bind_host_endian_p0, 0)); + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &connect_big_endian_p0, 0)); + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &bind_connect_host_endian_p1, 0)); + enforce_ruleset(_metadata, ruleset_fd); + + /* No restriction for big endinan CPU. */ + test_bind_and_connect(_metadata, &self->srv0, false, little_endian); + + /* No restriction for any CPU. */ + test_bind_and_connect(_metadata, &self->srv1, false, false); +} + +TEST_F(ipv4_tcp, with_fs) +{ + const struct landlock_ruleset_attr ruleset_attr_fs_net = { + .handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR, + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP, + }; + struct landlock_path_beneath_attr path_beneath = { + .allowed_access = LANDLOCK_ACCESS_FS_READ_DIR, + .parent_fd = -1, + }; + struct landlock_net_port_attr tcp_bind = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP, + .port = self->srv0.port, + }; + int ruleset_fd, bind_fd, dir_fd; + + /* Creates ruleset both for filesystem and network access. */ + ruleset_fd = landlock_create_ruleset(&ruleset_attr_fs_net, + sizeof(ruleset_attr_fs_net), 0); + ASSERT_LE(0, ruleset_fd); + + /* Adds a filesystem rule. */ + path_beneath.parent_fd = open("/dev", O_PATH | O_DIRECTORY | O_CLOEXEC); + ASSERT_LE(0, path_beneath.parent_fd); + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, + &path_beneath, 0)); + EXPECT_EQ(0, close(path_beneath.parent_fd)); + + /* Adds a network rule. */ + ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + + /* Tests file access. */ + dir_fd = open("/dev", O_RDONLY); + EXPECT_LE(0, dir_fd); + EXPECT_EQ(0, close(dir_fd)); + + dir_fd = open("/", O_RDONLY); + EXPECT_EQ(-1, dir_fd); + EXPECT_EQ(EACCES, errno); + + /* Tests port binding. */ + bind_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + ASSERT_LE(0, bind_fd); + EXPECT_EQ(0, bind_variant(bind_fd, &self->srv0)); + EXPECT_EQ(0, close(bind_fd)); + + bind_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); + ASSERT_LE(0, bind_fd); + EXPECT_EQ(-EACCES, bind_variant(bind_fd, &self->srv1)); +} + +FIXTURE(port_specific) +{ + struct service_fixture srv0; +}; + +FIXTURE_VARIANT(port_specific) +{ + const enum sandbox_type sandbox; + const struct protocol_variant prot; +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(port_specific, no_sandbox_with_ipv4) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_INET, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(port_specific, sandbox_with_ipv4) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_INET, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(port_specific, no_sandbox_with_ipv6) { + /* clang-format on */ + .sandbox = NO_SANDBOX, + .prot = { + .domain = AF_INET6, + .type = SOCK_STREAM, + }, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(port_specific, sandbox_with_ipv6) { + /* clang-format on */ + .sandbox = TCP_SANDBOX, + .prot = { + .domain = AF_INET6, + .type = SOCK_STREAM, + }, +}; + +FIXTURE_SETUP(port_specific) +{ + disable_caps(_metadata); + + ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0)); + + setup_loopback(_metadata); +}; + +FIXTURE_TEARDOWN(port_specific) +{ +} + +TEST_F(port_specific, bind_connect_zero) +{ + int bind_fd, connect_fd, ret; + uint16_t port; + + /* Adds a rule layer with bind and connect actions. */ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP + }; + const struct landlock_net_port_attr tcp_bind_connect_zero = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = 0, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + /* Checks zero port value on bind and connect actions. */ + EXPECT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect_zero, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + + connect_fd = socket_variant(&self->srv0); + ASSERT_LE(0, connect_fd); + + /* Sets address port to 0 for both protocol families. */ + set_port(&self->srv0, 0); + /* + * Binds on port 0, which selects a random port within + * ip_local_port_range. + */ + ret = bind_variant(bind_fd, &self->srv0); + EXPECT_EQ(0, ret); + + EXPECT_EQ(0, listen(bind_fd, backlog)); + + /* Connects on port 0. */ + ret = connect_variant(connect_fd, &self->srv0); + EXPECT_EQ(-ECONNREFUSED, ret); + + /* Sets binded port for both protocol families. */ + port = get_binded_port(bind_fd, &variant->prot); + EXPECT_NE(0, port); + set_port(&self->srv0, port); + /* Connects on the binded port. */ + ret = connect_variant(connect_fd, &self->srv0); + if (is_restricted(&variant->prot, variant->sandbox)) { + /* Denied by Landlock. */ + EXPECT_EQ(-EACCES, ret); + } else { + EXPECT_EQ(0, ret); + } + + EXPECT_EQ(0, close(connect_fd)); + EXPECT_EQ(0, close(bind_fd)); +} + +TEST_F(port_specific, bind_connect_1023) +{ + int bind_fd, connect_fd, ret; + + /* Adds a rule layer with bind and connect actions. */ + if (variant->sandbox == TCP_SANDBOX) { + const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP + }; + /* A rule with port value less than 1024. */ + const struct landlock_net_port_attr tcp_bind_connect_low_range = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = 1023, + }; + /* A rule with 1024 port. */ + const struct landlock_net_port_attr tcp_bind_connect = { + .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP, + .port = 1024, + }; + int ruleset_fd; + + ruleset_fd = landlock_create_ruleset(&ruleset_attr, + sizeof(ruleset_attr), 0); + ASSERT_LE(0, ruleset_fd); + + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect_low_range, 0)); + ASSERT_EQ(0, + landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT, + &tcp_bind_connect, 0)); + + enforce_ruleset(_metadata, ruleset_fd); + EXPECT_EQ(0, close(ruleset_fd)); + } + + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + + connect_fd = socket_variant(&self->srv0); + ASSERT_LE(0, connect_fd); + + /* Sets address port to 1023 for both protocol families. */ + set_port(&self->srv0, 1023); + /* Binds on port 1023. */ + ret = bind_variant(bind_fd, &self->srv0); + /* Denied by the system. */ + EXPECT_EQ(-EACCES, ret); + + /* Binds on port 1023. */ + set_cap(_metadata, CAP_NET_BIND_SERVICE); + ret = bind_variant(bind_fd, &self->srv0); + clear_cap(_metadata, CAP_NET_BIND_SERVICE); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, listen(bind_fd, backlog)); + + /* Connects on the binded port 1023. */ + ret = connect_variant(connect_fd, &self->srv0); + EXPECT_EQ(0, ret); + + EXPECT_EQ(0, close(connect_fd)); + EXPECT_EQ(0, close(bind_fd)); + + bind_fd = socket_variant(&self->srv0); + ASSERT_LE(0, bind_fd); + + connect_fd = socket_variant(&self->srv0); + ASSERT_LE(0, connect_fd); + + /* Sets address port to 1024 for both protocol families. */ + set_port(&self->srv0, 1024); + /* Binds on port 1024. */ + ret = bind_variant(bind_fd, &self->srv0); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, listen(bind_fd, backlog)); + + /* Connects on the binded port 1024. */ + ret = connect_variant(connect_fd, &self->srv0); + EXPECT_EQ(0, ret); + + EXPECT_EQ(0, close(connect_fd)); + EXPECT_EQ(0, close(bind_fd)); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/user_events/abi_test.c b/tools/testing/selftests/user_events/abi_test.c index f5575ef2007c..cef1ff1af223 100644 --- a/tools/testing/selftests/user_events/abi_test.c +++ b/tools/testing/selftests/user_events/abi_test.c @@ -24,6 +24,18 @@ const char *data_file = "/sys/kernel/tracing/user_events_data"; const char *enable_file = "/sys/kernel/tracing/events/user_events/__abi_event/enable"; +static bool event_exists(void) +{ + int fd = open(enable_file, O_RDWR); + + if (fd < 0) + return false; + + close(fd); + + return true; +} + static int change_event(bool enable) { int fd = open(enable_file, O_RDWR); @@ -47,7 +59,22 @@ static int change_event(bool enable) return ret; } -static int reg_enable(void *enable, int size, int bit) +static int event_delete(void) +{ + int fd = open(data_file, O_RDWR); + int ret; + + if (fd < 0) + return -1; + + ret = ioctl(fd, DIAG_IOCSDEL, "__abi_event"); + + close(fd); + + return ret; +} + +static int reg_enable_flags(void *enable, int size, int bit, int flags) { struct user_reg reg = {0}; int fd = open(data_file, O_RDWR); @@ -58,6 +85,7 @@ static int reg_enable(void *enable, int size, int bit) reg.size = sizeof(reg); reg.name_args = (__u64)"__abi_event"; + reg.flags = flags; reg.enable_bit = bit; reg.enable_addr = (__u64)enable; reg.enable_size = size; @@ -69,6 +97,11 @@ static int reg_enable(void *enable, int size, int bit) return ret; } +static int reg_enable(void *enable, int size, int bit) +{ + return reg_enable_flags(enable, size, bit, 0); +} + static int reg_disable(void *enable, int bit) { struct user_unreg reg = {0}; @@ -128,6 +161,26 @@ TEST_F(user, enablement) { ASSERT_EQ(0, change_event(false)); } +TEST_F(user, flags) { + /* USER_EVENT_REG_PERSIST is allowed */ + ASSERT_EQ(0, reg_enable_flags(&self->check, sizeof(int), 0, + USER_EVENT_REG_PERSIST)); + ASSERT_EQ(0, reg_disable(&self->check, 0)); + + /* Ensure it exists after close and disable */ + ASSERT_TRUE(event_exists()); + + /* Ensure we can delete it */ + ASSERT_EQ(0, event_delete()); + + /* USER_EVENT_REG_MAX or above is not allowed */ + ASSERT_EQ(-1, reg_enable_flags(&self->check, sizeof(int), 0, + USER_EVENT_REG_MAX)); + + /* Ensure it does not exist after invalid flags */ + ASSERT_FALSE(event_exists()); +} + TEST_F(user, bit_sizes) { /* Allow 0-31 bits for 32-bit */ ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); diff --git a/tools/testing/selftests/user_events/dyn_test.c b/tools/testing/selftests/user_events/dyn_test.c index a85980190bea..bdf9ab127488 100644 --- a/tools/testing/selftests/user_events/dyn_test.c +++ b/tools/testing/selftests/user_events/dyn_test.c @@ -17,9 +17,25 @@ #include "../kselftest_harness.h" #include "user_events_selftests.h" +const char *dyn_file = "/sys/kernel/tracing/dynamic_events"; const char *abi_file = "/sys/kernel/tracing/user_events_data"; const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable"; +static int event_delete(void) +{ + int fd = open(abi_file, O_RDWR); + int ret; + + if (fd < 0) + return -1; + + ret = ioctl(fd, DIAG_IOCSDEL, "__test_event"); + + close(fd); + + return ret; +} + static bool wait_for_delete(void) { int i; @@ -64,7 +80,31 @@ static int unreg_event(int fd, int *check, int bit) return ioctl(fd, DIAG_IOCSUNREG, &unreg); } -static int parse(int *check, const char *value) +static int parse_dyn(const char *value) +{ + int fd = open(dyn_file, O_RDWR | O_APPEND); + int len = strlen(value); + int ret; + + if (fd == -1) + return -1; + + ret = write(fd, value, len); + + if (ret == len) + ret = 0; + else + ret = -1; + + close(fd); + + if (ret == 0) + event_delete(); + + return ret; +} + +static int parse_abi(int *check, const char *value) { int fd = open(abi_file, O_RDWR); int ret; @@ -90,6 +130,18 @@ static int parse(int *check, const char *value) return ret; } +static int parse(int *check, const char *value) +{ + int abi_ret = parse_abi(check, value); + int dyn_ret = parse_dyn(value); + + /* Ensure both ABI and DYN parse the same way */ + if (dyn_ret != abi_ret) + return -1; + + return dyn_ret; +} + static int check_match(int *check, const char *first, const char *second, bool *match) { int fd = open(abi_file, O_RDWR); diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c index 623a38908ed5..c769d7b3842c 100644 --- a/tools/tracing/rtla/src/utils.c +++ b/tools/tracing/rtla/src/utils.c @@ -538,7 +538,7 @@ static const int find_mount(const char *fs, char *mp, int sizeof_mp) { char mount_point[MAX_PATH]; char type[100]; - int found; + int found = 0; FILE *fp; fp = fopen("/proc/mounts", "r"); diff --git a/tools/verification/dot2/dot2k b/tools/verification/dot2/dot2k index 9dcd38abe20a..d4d7e52d549e 100644 --- a/tools/verification/dot2/dot2k +++ b/tools/verification/dot2/dot2k @@ -15,8 +15,6 @@ if __name__ == '__main__': import os import platform import sys - import sys - import argparse parser = argparse.ArgumentParser(description='transform .dot file into kernel rv monitor') parser.add_argument('-d', "--dot", dest="dot_file", required=True)