Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
fd6d90d8
Commit
fd6d90d8
authored
Feb 13, 2017
by
davidcunado-arm
Committed by
GitHub
Feb 13, 2017
Browse files
Merge pull request #826 from dp-arm/dp/psci-stat-abstraction
Decouple PSCI stat residency calculation from PMF
parents
4d07e782
e5bbd16a
Changes
12
Show whitespace changes
Inline
Side-by-side
Makefile
View file @
fd6d90d8
...
...
@@ -346,11 +346,6 @@ ifneq (${GENERATE_COT},0)
endif
endif
# Make sure PMF is enabled if PSCI STAT is enabled.
ifeq (${ENABLE_PSCI_STAT},1)
ENABLE_PMF := 1
endif
ifneq (${FIP_ALIGN},0)
FIP_ARGS += --align ${FIP_ALIGN}
endif
...
...
docs/porting-guide.md
View file @
fd6d90d8
...
...
@@ -1707,10 +1707,56 @@ level could enter. It depends on the `validate_power_state()` handler to
convert the power-state parameter (possibly encoding a composite power state)
passed in a PSCI
`CPU_SUSPEND`
call to this representation.
The following functions must be implemented to initialize PSCI functionality in
the ARM Trusted Firmware.
The following functions form part of platform port of PSCI functionality.
### Function : plat_psci_stat_accounting_start() [optional]
Argument : const psci_power_state_t *
Return : void
This is an optional hook that platforms can implement for residency statistics
accounting before entering a low power state. The
`pwr_domain_state`
field of
`state_info`
(first argument) can be inspected if stat accounting is done
differently at CPU level versus higher levels. As an example, if the element at
index 0 (CPU power level) in the
`pwr_domain_state`
array indicates a power down
state, special hardware logic may be programmed in order to keep track of the
residency statistics. For higher levels (array indices > 0), the residency
statistics could be tracked in software using PMF. If
`ENABLE_PMF`
is set, the
default implementation will use PMF to capture timestamps.
### Function : plat_psci_stat_accounting_stop() [optional]
Argument : const psci_power_state_t *
Return : void
This is an optional hook that platforms can implement for residency statistics
accounting after exiting from a low power state. The
`pwr_domain_state`
field
of
`state_info`
(first argument) can be inspected if stat accounting is done
differently at CPU level versus higher levels. As an example, if the element at
index 0 (CPU power level) in the
`pwr_domain_state`
array indicates a power down
state, special hardware logic may be programmed in order to keep track of the
residency statistics. For higher levels (array indices > 0), the residency
statistics could be tracked in software using PMF. If
`ENABLE_PMF`
is set, the
default implementation will use PMF to capture timestamps.
### Function : plat_psci_stat_get_residency() [optional]
Argument : unsigned int, const psci_power_state_t *, int
Return : u_register_t
This is an optional interface that is is invoked after resuming from a low power
state and provides the time spent resident in that low power state by the power
domain at a particular power domain level. When a CPU wakes up from suspend,
all its parent power domain levels are also woken up. The generic PSCI code
invokes this function for each parent power domain that is resumed and it
identified by the
`lvl`
(first argument) parameter. The
`state_info`
(second
argument) describes the low power state that the power domain has resumed from.
The current CPU is the first CPU in the power domain to resume from the low
power state and the
`last_cpu_idx`
(third parameter) is the index of the last
CPU in the power domain to suspend and may be needed to calculate the residency
for that power domain.
### Function : plat_get_target_pwr_state() [optional]
Argument : unsigned int, const plat_local_state_t *, unsigned int
...
...
docs/user-guide.md
View file @
fd6d90d8
...
...
@@ -274,8 +274,9 @@ performed.
*
`ENABLE_PSCI_STAT`
: Boolean option to enable support for optional PSCI
functions
`PSCI_STAT_RESIDENCY`
and
`PSCI_STAT_COUNT`
. Default is 0.
Enabling this option enables the
`ENABLE_PMF`
build option as well.
The PMF is used for collecting the statistics.
In the absence of an alternate stat collection backend,
`ENABLE_PMF`
must
be enabled. If
`ENABLE_PMF`
is set, the residency statistics are tracked in
software.
*
`ENABLE_RUNTIME_INSTRUMENTATION`
: Boolean option to enable runtime
instrumentation which injects timestamp collection points into
...
...
include/plat/common/platform.h
View file @
fd6d90d8
/*
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
7
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -254,6 +254,11 @@ const unsigned char *plat_get_power_domain_tree_desc(void);
/*******************************************************************************
* Optional PSCI functions (BL31).
******************************************************************************/
void
plat_psci_stat_accounting_start
(
const
psci_power_state_t
*
state_info
);
void
plat_psci_stat_accounting_stop
(
const
psci_power_state_t
*
state_info
);
u_register_t
plat_psci_stat_get_residency
(
unsigned
int
lvl
,
const
psci_power_state_t
*
state_info
,
int
last_cpu_index
);
plat_local_state_t
plat_get_target_pwr_state
(
unsigned
int
lvl
,
const
plat_local_state_t
*
states
,
unsigned
int
ncpu
);
...
...
lib/psci/psci_common.c
View file @
fd6d90d8
/*
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
7
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -760,13 +760,7 @@ void psci_warmboot_entrypoint(void)
cpu_idx
);
#if ENABLE_PSCI_STAT
/*
* Capture power up time-stamp.
* No cache maintenance is required as caches are off
* and writes are direct to the main memory.
*/
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_EXIT_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
plat_psci_stat_accounting_stop
(
&
state_info
);
#endif
psci_get_target_local_pwr_states
(
end_pwrlvl
,
&
state_info
);
...
...
@@ -801,7 +795,7 @@ void psci_warmboot_entrypoint(void)
* Since caches are now enabled, it's necessary to do cache
* maintenance before reading that same data.
*/
psci_stats_update_pwr_up
(
end_pwrlvl
,
&
state_info
,
PMF_CACHE_MAINT
);
psci_stats_update_pwr_up
(
end_pwrlvl
,
&
state_info
);
#endif
/*
...
...
lib/psci/psci_main.c
View file @
fd6d90d8
/*
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
7
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -117,13 +117,7 @@ int psci_cpu_suspend(unsigned int power_state,
psci_set_cpu_local_state
(
cpu_pd_state
);
#if ENABLE_PSCI_STAT
/*
* Capture time-stamp before CPU standby
* No cache maintenance is needed as caches
* are ON through out the CPU standby operation.
*/
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
plat_psci_stat_accounting_start
(
&
state_info
);
#endif
#if ENABLE_RUNTIME_INSTRUMENTATION
...
...
@@ -144,13 +138,10 @@ int psci_cpu_suspend(unsigned int power_state,
#endif
#if ENABLE_PSCI_STAT
/* Capture time-stamp after CPU standby */
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_EXIT_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
plat_psci_stat_accounting_stop
(
&
state_info
);
/* Update PSCI stats */
psci_stats_update_pwr_up
(
PSCI_CPU_PWR_LVL
,
&
state_info
,
PMF_NO_CACHE_MAINT
);
psci_stats_update_pwr_up
(
PSCI_CPU_PWR_LVL
,
&
state_info
);
#endif
return
PSCI_E_SUCCESS
;
...
...
lib/psci/psci_off.c
View file @
fd6d90d8
/*
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
7
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -137,13 +137,7 @@ int psci_do_cpu_off(unsigned int end_pwrlvl)
psci_plat_pm_ops
->
pwr_domain_off
(
&
state_info
);
#if ENABLE_PSCI_STAT
/*
* Capture time-stamp while entering low power state.
* No cache maintenance needed because caches are off
* and writes are direct to main memory.
*/
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
plat_psci_stat_accounting_start
(
&
state_info
);
#endif
exit:
...
...
lib/psci/psci_private.h
View file @
fd6d90d8
/*
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
7
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -35,7 +35,6 @@
#include <bakery_lock.h>
#include <bl_common.h>
#include <cpu_data.h>
#include <pmf.h>
#include <psci.h>
#include <spinlock.h>
...
...
@@ -106,15 +105,6 @@
#define is_cpu_standby_req(is_power_down_state, retn_lvl) \
(((!(is_power_down_state)) && ((retn_lvl) == 0)) ? 1 : 0)
/* Following are used as ID's to capture time-stamp */
#define PSCI_STAT_ID_ENTER_LOW_PWR 0
#define PSCI_STAT_ID_EXIT_LOW_PWR 1
#define PSCI_STAT_TOTAL_IDS 2
/* Declare PMF service functions for PSCI */
PMF_DECLARE_CAPTURE_TIMESTAMP
(
psci_svc
)
PMF_DECLARE_GET_TIMESTAMP
(
psci_svc
)
/*******************************************************************************
* The following two data structures implement the power domain tree. The tree
* is used to track the state of all the nodes i.e. power domain instances
...
...
@@ -246,8 +236,7 @@ void __dead2 psci_system_reset(void);
void
psci_stats_update_pwr_down
(
unsigned
int
end_pwrlvl
,
const
psci_power_state_t
*
state_info
);
void
psci_stats_update_pwr_up
(
unsigned
int
end_pwrlvl
,
const
psci_power_state_t
*
state_info
,
unsigned
int
flags
);
const
psci_power_state_t
*
state_info
);
u_register_t
psci_stat_residency
(
u_register_t
target_cpu
,
unsigned
int
power_state
);
u_register_t
psci_stat_count
(
u_register_t
target_cpu
,
...
...
lib/psci/psci_stat.c
View file @
fd6d90d8
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016
-2017
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -38,9 +38,6 @@
#define PLAT_MAX_PWR_LVL_STATES 2
#endif
/* Ticks elapsed in one second by a signal of 1 MHz */
#define MHZ_TICKS_PER_SEC 1000000
/* Following structure is used for PSCI STAT */
typedef
struct
psci_stat
{
u_register_t
residency
;
...
...
@@ -62,27 +59,6 @@ static psci_stat_t psci_cpu_stat[PLATFORM_CORE_COUNT]
static
psci_stat_t
psci_non_cpu_stat
[
PSCI_NUM_NON_CPU_PWR_DOMAINS
]
[
PLAT_MAX_PWR_LVL_STATES
];
/* Register PMF PSCI service */
PMF_REGISTER_SERVICE
(
psci_svc
,
PMF_PSCI_STAT_SVC_ID
,
PSCI_STAT_TOTAL_IDS
,
PMF_STORE_ENABLE
)
/* The divisor to use to convert raw timestamp into microseconds */
u_register_t
residency_div
;
/*
* This macro calculates the stats residency in microseconds,
* taking in account the wrap around condition.
*/
#define calc_stat_residency(_pwrupts, _pwrdnts, _res) \
do { \
if (_pwrupts < _pwrdnts) \
_res = UINT64_MAX - _pwrdnts + _pwrupts;\
else \
_res = _pwrupts - _pwrdnts; \
/* Convert timestamp into microseconds */
\
_res = _res/residency_div; \
} while (0)
/*
* This functions returns the index into the `psci_stat_t` array given the
* local power state and power domain level. If the platform implements the
...
...
@@ -150,44 +126,23 @@ void psci_stats_update_pwr_down(unsigned int end_pwrlvl,
* It is called with caches enabled and locks acquired(for NON-CPU domain)
******************************************************************************/
void
psci_stats_update_pwr_up
(
unsigned
int
end_pwrlvl
,
const
psci_power_state_t
*
state_info
,
unsigned
int
flags
)
const
psci_power_state_t
*
state_info
)
{
int
parent_idx
,
cpu_idx
=
plat_my_core_pos
();
int
lvl
,
stat_idx
;
plat_local_state_t
local_state
;
unsigned
long
long
pwrup_ts
=
0
,
pwrdn_ts
=
0
;
u_register_t
residency
;
assert
(
end_pwrlvl
<=
PLAT_MAX_PWR_LVL
);
assert
(
state_info
);
/* Initialize the residency divisor if not already initialized */
if
(
!
residency_div
)
{
/* Pre-calculate divisor so that it can be directly used to
convert time-stamp into microseconds */
residency_div
=
read_cntfrq_el0
()
/
MHZ_TICKS_PER_SEC
;
assert
(
residency_div
);
}
/* Get power down time-stamp for current CPU */
PMF_GET_TIMESTAMP_BY_INDEX
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
cpu_idx
,
flags
,
pwrdn_ts
);
/* In the case of 1st power on just return */
if
(
!
pwrdn_ts
)
return
;
/* Get power up time-stamp for current CPU */
PMF_GET_TIMESTAMP_BY_INDEX
(
psci_svc
,
PSCI_STAT_ID_EXIT_LOW_PWR
,
cpu_idx
,
flags
,
pwrup_ts
);
/* Get the index into the stats array */
local_state
=
state_info
->
pwr_domain_state
[
PSCI_CPU_PWR_LVL
];
stat_idx
=
get_stat_idx
(
local_state
,
PSCI_CPU_PWR_LVL
);
/* Calculate stats residency */
calc_stat_residency
(
pwrup_ts
,
pwrdn_ts
,
residency
);
/* Call into platform interface to calculate residency. */
residency
=
plat_psci_stat_get_residency
(
PSCI_CPU_PWR_LVL
,
state_info
,
cpu_idx
);
/* Update CPU stats. */
psci_cpu_stat
[
cpu_idx
][
stat_idx
].
residency
+=
residency
;
...
...
@@ -207,10 +162,9 @@ void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
assert
(
last_cpu_in_non_cpu_pd
[
parent_idx
]
!=
-
1
);
/* Get power down time-stamp for last CPU */
PMF_GET_TIMESTAMP_BY_INDEX
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
last_cpu_in_non_cpu_pd
[
parent_idx
],
flags
,
pwrdn_ts
);
/* Call into platform interface to calculate residency. */
residency
=
plat_psci_stat_get_residency
(
lvl
,
state_info
,
last_cpu_in_non_cpu_pd
[
parent_idx
]);
/* Initialize back to reset value */
last_cpu_in_non_cpu_pd
[
parent_idx
]
=
-
1
;
...
...
@@ -218,9 +172,6 @@ void psci_stats_update_pwr_up(unsigned int end_pwrlvl,
/* Get the index into the stats array */
stat_idx
=
get_stat_idx
(
local_state
,
lvl
);
/* Calculate stats residency */
calc_stat_residency
(
pwrup_ts
,
pwrdn_ts
,
residency
);
/* Update non cpu stats */
psci_non_cpu_stat
[
parent_idx
][
stat_idx
].
residency
+=
residency
;
psci_non_cpu_stat
[
parent_idx
][
stat_idx
].
count
++
;
...
...
lib/psci/psci_suspend.c
View file @
fd6d90d8
/*
* Copyright (c) 2013-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-201
7
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -211,13 +211,7 @@ void psci_cpu_suspend_start(entry_point_info_t *ep,
psci_plat_pm_ops
->
pwr_domain_suspend
(
state_info
);
#if ENABLE_PSCI_STAT
/*
* Capture time-stamp while entering low power state.
* No cache maintenance needed because caches are off
* and writes are direct to main memory.
*/
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
plat_psci_stat_accounting_start
(
state_info
);
#endif
exit:
...
...
@@ -257,6 +251,10 @@ exit:
PMF_NO_CACHE_MAINT
);
#endif
#if ENABLE_PSCI_STAT
plat_psci_stat_accounting_start
(
state_info
);
#endif
/*
* We will reach here if only retention/standby states have been
* requested at multiple power levels. This means that the cpu
...
...
@@ -264,6 +262,11 @@ exit:
*/
wfi
();
#if ENABLE_PSCI_STAT
plat_psci_stat_accounting_stop
(
state_info
);
psci_stats_update_pwr_up
(
end_pwrlvl
,
state_info
);
#endif
#if ENABLE_RUNTIME_INSTRUMENTATION
PMF_CAPTURE_TIMESTAMP
(
rt_instr_svc
,
RT_INSTR_EXIT_HW_LOW_PWR
,
...
...
plat/arm/common/arm_common.mk
View file @
fd6d90d8
#
# Copyright (c) 2015-201
6
, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2015-201
7
, ARM Limited and Contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
...
...
@@ -92,6 +92,7 @@ $(eval $(call add_define,ARM_BL31_IN_DRAM))
# Enable PSCI_STAT_COUNT/RESIDENCY APIs on ARM platforms
ENABLE_PSCI_STAT
:=
1
ENABLE_PMF
:=
1
# On ARM platforms, separate the code and read-only data sections to allow
# mapping the former as executable and the latter as execute-never.
...
...
plat/common/plat_psci_common.c
View file @
fd6d90d8
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016
-2017
, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
...
...
@@ -31,8 +31,125 @@
#include <arch.h>
#include <assert.h>
#include <platform.h>
#include <pmf.h>
#include <psci.h>
#if ENABLE_PSCI_STAT && ENABLE_PMF
#pragma weak plat_psci_stat_accounting_start
#pragma weak plat_psci_stat_accounting_stop
#pragma weak plat_psci_stat_get_residency
/* Ticks elapsed in one second by a signal of 1 MHz */
#define MHZ_TICKS_PER_SEC 1000000
/* Following are used as ID's to capture time-stamp */
#define PSCI_STAT_ID_ENTER_LOW_PWR 0
#define PSCI_STAT_ID_EXIT_LOW_PWR 1
#define PSCI_STAT_TOTAL_IDS 2
PMF_REGISTER_SERVICE
(
psci_svc
,
PMF_PSCI_STAT_SVC_ID
,
PSCI_STAT_TOTAL_IDS
,
PMF_STORE_ENABLE
)
/*
* This function calculates the stats residency in microseconds,
* taking in account the wrap around condition.
*/
static
u_register_t
calc_stat_residency
(
unsigned
long
long
pwrupts
,
unsigned
long
long
pwrdnts
)
{
/* The divisor to use to convert raw timestamp into microseconds. */
u_register_t
residency_div
;
u_register_t
res
;
/*
* Calculate divisor so that it can be directly used to
* convert time-stamp into microseconds.
*/
residency_div
=
read_cntfrq_el0
()
/
MHZ_TICKS_PER_SEC
;
assert
(
residency_div
);
if
(
pwrupts
<
pwrdnts
)
res
=
UINT64_MAX
-
pwrdnts
+
pwrupts
;
else
res
=
pwrupts
-
pwrdnts
;
return
res
/
residency_div
;
}
/*
* Capture timestamp before entering a low power state.
* No cache maintenance is required when capturing the timestamp.
* Cache maintenance may be needed when reading these timestamps.
*/
void
plat_psci_stat_accounting_start
(
__unused
const
psci_power_state_t
*
state_info
)
{
assert
(
state_info
);
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
}
/*
* Capture timestamp after exiting a low power state.
* No cache maintenance is required when capturing the timestamp.
* Cache maintenance may be needed when reading these timestamps.
*/
void
plat_psci_stat_accounting_stop
(
__unused
const
psci_power_state_t
*
state_info
)
{
assert
(
state_info
);
PMF_CAPTURE_TIMESTAMP
(
psci_svc
,
PSCI_STAT_ID_EXIT_LOW_PWR
,
PMF_NO_CACHE_MAINT
);
}
/*
* Calculate the residency for the given level and power state
* information.
*/
u_register_t
plat_psci_stat_get_residency
(
unsigned
int
lvl
,
const
psci_power_state_t
*
state_info
,
int
last_cpu_idx
)
{
plat_local_state_t
state
;
unsigned
long
long
pwrup_ts
=
0
,
pwrdn_ts
=
0
;
unsigned
int
pmf_flags
;
assert
(
lvl
>=
PSCI_CPU_PWR_LVL
&&
lvl
<=
PLAT_MAX_PWR_LVL
);
assert
(
state_info
);
assert
(
last_cpu_idx
>=
0
&&
last_cpu_idx
<=
PLATFORM_CORE_COUNT
);
if
(
lvl
==
PSCI_CPU_PWR_LVL
)
assert
(
last_cpu_idx
==
plat_my_core_pos
());
/*
* If power down is requested, then timestamp capture will
* be with caches OFF. Hence we have to do cache maintenance
* when reading the timestamp.
*/
state
=
state_info
->
pwr_domain_state
[
PSCI_CPU_PWR_LVL
];
if
(
is_local_state_off
(
state
))
{
pmf_flags
=
PMF_CACHE_MAINT
;
}
else
{
assert
(
is_local_state_retn
(
state
));
pmf_flags
=
PMF_NO_CACHE_MAINT
;
}
PMF_GET_TIMESTAMP_BY_INDEX
(
psci_svc
,
PSCI_STAT_ID_ENTER_LOW_PWR
,
last_cpu_idx
,
pmf_flags
,
pwrdn_ts
);
PMF_GET_TIMESTAMP_BY_INDEX
(
psci_svc
,
PSCI_STAT_ID_EXIT_LOW_PWR
,
plat_my_core_pos
(),
pmf_flags
,
pwrup_ts
);
return
calc_stat_residency
(
pwrup_ts
,
pwrdn_ts
);
}
#endif
/* ENABLE_PSCI_STAT && ENABLE_PMF */
/*
* The PSCI generic code uses this API to let the platform participate in state
* coordination during a power management operation. It compares the platform
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment