Commit Graph

2906 Commits

Author SHA1 Message Date
davidcunado-arm c195f1a705
Merge pull request #1152 from jeenu-arm/ehf-and-sdei
EHF and SDEI
2017-11-13 10:58:40 +00:00
Jeenu Viswambharan cafad7be04 docs: Add SDEI dispatcher documentation
The document includes SDEI sequence diagrams that are generated using
PlantUML [1].

A shell script is introduced to generate SVG files from PlantUML files
supplied in arguments.

[1] http://plantuml.com/PlantUML_Language_Reference_Guide.pdf

Change-Id: I433897856810bf1927f2800a7b2b1d81827c69b2
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan 55a1266ec8 SDEI: Add API for explicit dispatch
This allows for other EL3 components to schedule an SDEI event dispatch
to Normal world upon the next ERET. The API usage constrains are set out
in the SDEI dispatcher documentation.

Documentation to follow.

Change-Id: Id534bae0fd85afc94523490098c81f85c4e8f019
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan 0baec2abde ARM platforms: Enable SDEI
Support SDEI on ARM platforms using frameworks implemented in earlier
patches by defining and exporting SDEI events: this patch defines the
standard event 0, and a handful of shared and private dynamic events.

Change-Id: I9d3d92a92cff646b8cc55eabda78e140deaa24e1
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan 0bef0edffd ARM platforms: Define exception macros
Define number of priority bits, and allocate priority levels for SDEI.

Change-Id: Ib6bb6c5c09397f7caef950c4caed5a737b3d4112
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan 781f4aac76 ARM platforms: Provide SDEI entry point validation
Provide a strong definition for plat_sdei_validate_sdei_entrypoint()
which translates client address to Physical Address, and then validating
the address to be present in DRAM.

Change-Id: Ib93eb66b413d638aa5524d1b3de36aa16d38ea11
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan 71e7a4e568 ARM platforms: Make arm_validate_ns_entrypoint() common
The function arm_validate_ns_entrypoint() validates a given non-secure
physical address. This function however specifically returns PSCI error
codes.

Non-secure physical address validation is potentially useful across ARM
platforms, even for non-PSCI use cases. Therefore make this function
common by returning 0 for success or -1 otherwise.

Having made the function common, make arm_validate_psci_entrypoint() a
wrapper around arm_validate_ns_entrypoint() which only translates return
value into PSCI error codes. This wrapper is now used where
arm_validate_ns_entrypoint() was currently used for PSCI entry point
validation.

Change-Id: Ic781fc3105d6d199fd8f53f01aba5baea0ebc310
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan b7cb133e5c BL31: Add SDEI dispatcher
The implementation currently supports only interrupt-based SDEI events,
and supports all interfaces as defined by SDEI specification version
1.0 [1].

Introduce the build option SDEI_SUPPORT to include SDEI dispatcher in
BL31.

Update user guide and porting guide. SDEI documentation to follow.

[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf

Change-Id: I758b733084e4ea3b27ac77d0259705565842241a
Co-authored-by: Yousuf A <yousuf.sait@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 08:38:51 +00:00
Jeenu Viswambharan 3d732e23e7 BL31: Program Priority Mask for SMC handling
On GICv3 systems, as a side effect of adding provision to handle EL3
interrupts (unconditionally routing FIQs to EL3), pending Non-secure
interrupts (signalled as FIQs) may preempt execution in lower Secure ELs
[1]. This will inadvertently disrupt the semantics of Fast SMC
(previously called Atomic SMC) calls.

To retain semantics of Fast SMCs, the GIC PMR must be programmed to
prevent Non-secure interrupts from preempting Secure execution. To that
effect, two new functions in the Exception Handling Framework subscribe
to events introduced in an earlier commit:

  - Upon 'cm_exited_normal_world', the Non-secure PMR is stashed, and
    the PMR is programmed to the highest Non-secure interrupt priority.

  - Upon 'cm_entering_normal_world', the previously stashed Non-secure
    PMR is restored.

The above sequence however prevents Yielding SMCs from being preempted
by Non-secure interrupts as intended. To facilitate this, the public API
exc_allow_ns_preemption() is introduced that programs the PMR to the
original Non-secure PMR value. Another API
exc_is_ns_preemption_allowed() is also introduced to check if
exc_allow_ns_preemption() had been called previously.

API documentation to follow.

[1] On GICv2 systems, this isn't a problem as, unlike GICv3, pending NS
    IRQs during Secure execution are signalled as IRQs, which aren't
    routed to EL3.

Change-Id: Ief96b162b0067179b1012332cd991ee1b3051dd0
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 07:49:30 +00:00
Jeenu Viswambharan 21b818c05f BL31: Introduce Exception Handling Framework
EHF is a framework that allows dispatching of EL3 interrupts to their
respective handlers in EL3.

This framework facilitates the firmware-first error handling policy in
which asynchronous exceptions may be routed to EL3. Such exceptions may
be handed over to respective exception handlers. Individual handlers
might further delegate exception handling to lower ELs.

The framework associates the delegated execution to lower ELs with a
priority value. For interrupts, this corresponds to the priorities
programmed in GIC; for other types of exceptions, viz. SErrors or
Synchronous External Aborts, individual dispatchers shall explicitly
associate delegation to a secure priority. In order to prevent lower
priority interrupts from preempting higher priority execution, the
framework provides helpers to control preemption by virtue of
programming Priority Mask register in the interrupt controller.

This commit allows for handling interrupts targeted at EL3. Exception
handlers own interrupts by assigning them a range of secure priorities,
and registering handlers for each priority range it owns.

Support for exception handling in BL31 image is enabled by setting the
build option EL3_EXCEPTION_HANDLING=1.

Documentation to follow.

NOTE: The framework assumes the priority scheme supported by platform
interrupt controller is compliant with that of ARM GIC architecture (v2
or later).

Change-Id: I7224337e4cea47c6ca7d7a4ca22a3716939f7e42
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 07:49:30 +00:00
Jeenu Viswambharan 4ee8d0becd GIC: Introduce API to get interrupt ID
Acknowledging interrupt shall return a raw value from the interrupt
controller in which the actual interrupt ID may be encoded. Add a
platform API to extract the actual interrupt ID from the raw value
obtained from interrupt controller.

Document the new function. Also clarify the semantics of interrupt
acknowledge.

Change-Id: I818dad7be47661658b16f9807877d259eb127405
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 07:49:30 +00:00
Jeenu Viswambharan 385f1dbb29 GIC: Fix Group 0 enabling
At present, the GIC drivers enable Group 0 interrupts only if there are
Secure SPIs listed in the interrupt properties/list. This means that,
even if there are Group 0 SGIs/PPIs configured, the group remained
disabled in the absence of a Group 0 SPI.

Modify both GICv2 and GICv3 SGI/PPI configuration to enable Group 0 when
corresponding SGIs/PPIs are present.

Change-Id: Id123e8aaee0c22b476eebe3800340906d83bbc6d
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 07:49:30 +00:00
Jeenu Viswambharan 058efeef98 GICv2: Fix populating PE target data
This patch brings in the following fixes:

  - The per-PE target data initialized during power up needs to be
    flushed so as to be visible to other PEs.

  - Setup per-PE target data for the primary PE as well. At present,
    this was only setup for secondary PEs when they were powered on.

Change-Id: Ibe3a57c14864e37b2326dd7ab321a5c7bf80e8af
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
2017-11-13 07:49:30 +00:00
davidcunado-arm bf2de7e499
Merge pull request #1158 from antonio-nino-diaz-arm/an/spm-fix
SPM: Fix pointer to MP info in boot info struct
2017-11-10 16:11:32 +00:00
Antonio Nino Diaz ff7d08052b SPM: Fix pointer to MP info in boot info struct
The MP info struct is placed right after the boot info struct. However,
when calculating the address of the MP info, the size of the boot info
struct was being multiplied by the size of the MP boot info. This left
a big gap of empty space between the structs.

This didn't break any code because the boot info struct has a pointer to
the MP info struct. It was just wasting space.

Change-Id: I1668e3540d9173261968f6740623549000bd48db
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-11-10 15:21:31 +00:00
davidcunado-arm 9500d5a438
Merge pull request #1148 from antonio-nino-diaz-arm/an/spm
Introduce Secure Partition Manager
2017-11-09 22:38:37 +00:00
Antonio Nino Diaz e29efeb1b4 SPM: FVP: Introduce port of SPM
This initial port of the Secure Partitions Manager to FVP supports BL31
in both SRAM and Trusted DRAM.

A document with instructions to build the SPM has been added.

Change-Id: I4ea83ff0a659be77f2cd72eaf2302cdf8ba98b32
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Co-authored-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: Achin Gupta <achin.gupta@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-11-09 11:34:09 +00:00
Antonio Nino Diaz 2fccb22804 SPM: Introduce Secure Partition Manager
A Secure Partition is a software execution environment instantiated in
S-EL0 that can be used to implement simple management and security
services. Since S-EL0 is an unprivileged exception level, a Secure
Partition relies on privileged firmware e.g. ARM Trusted Firmware to be
granted access to system and processor resources. Essentially, it is a
software sandbox that runs under the control of privileged software in
the Secure World and accesses the following system resources:

- Memory and device regions in the system address map.
- PE system registers.
- A range of asynchronous exceptions e.g. interrupts.
- A range of synchronous exceptions e.g. SMC function identifiers.

A Secure Partition enables privileged firmware to implement only the
absolutely essential secure services in EL3 and instantiate the rest in
a partition. Since the partition executes in S-EL0, its implementation
cannot be overly complex.

The component in ARM Trusted Firmware responsible for managing a Secure
Partition is called the Secure Partition Manager (SPM). The SPM is
responsible for the following:

- Validating and allocating resources requested by a Secure Partition.
- Implementing a well defined interface that is used for initialising a
  Secure Partition.
- Implementing a well defined interface that is used by the normal world
  and other secure services for accessing the services exported by a
  Secure Partition.
- Implementing a well defined interface that is used by a Secure
  Partition to fulfil service requests.
- Instantiating the software execution environment required by a Secure
  Partition to fulfil a service request.

Change-Id: I6f7862d6bba8732db5b73f54e789d717a35e802f
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Co-authored-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: Achin Gupta <achin.gupta@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-11-08 18:05:14 +00:00
Antonio Nino Diaz ad02a7596f xlat: Make function to calculate TCR PA bits public
This function can be useful to setup TCR_ELx by callers that don't use
the translation tables library to setup the system registers related
to them. By making it common, it can be reused whenever it is needed
without duplicating code.

Change-Id: Ibfada9e846d2a6cd113b1925ac911bb27327d375
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-11-08 18:05:14 +00:00
Antonio Nino Diaz 92cad5fa4b spd: Use `ENABLE_ASSERTIONS` instead of `DEBUG`
A line in the upstream SPDs is only compiled in in `DEBUG` builds. This
line is used to help with assertions and so assertion failures can
happen in release builds with assertions enabled. Use
`ENABLE_ASSERTIONS` instead of `DEBUG`.

This bug was introduced in commit aa61368eb5, which introduced the build
option `ENABLE_ASSERTIONS`.

Change-Id: I7977df9c89c68677b00099b2a1926fa3cb0937c6
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2017-11-08 18:05:14 +00:00
davidcunado-arm 8705ec8990
Merge pull request #1154 from soby-mathew/sm/fix_psci_stat
Fix PSCI STAT time stamp collection
2017-11-08 14:17:01 +00:00
Etienne Carriere 1d791530d0 ARMv7: division support for missing __aeabi_*divmod
ARMv7-A architectures that do not support the Virtualization extensions
do not support instructions for the 32bit division. This change provides
a software implementation for 32bit division.

The division implementation is dumped from the OP-TEE project
http://github.com/OP-TEE/optee_os. The code was slightly modified
to pass trusted firmware checkpatch requirements and copyright is
given to the ARM trusted firmware initiative and its contributors.

Change-Id: Idae0c7b80a0d75eac9bd41ae121921d4c5af3fa3
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 14:42:07 +01:00
Etienne Carriere 64deed19e4 ARMv7: GICv2 driver can manage GICv1 with security extension
Some SoCs integrate a GIC in version 1 that is currently not supported
by the trusted firmware. This change hijacks GICv2 driver to handle the
GICv1 as GICv1 is compatible enough with GICv2 as far as the platform
does not attempt to play with virtualization support or some GICv2
specific power features.

Note that current trusted firmware does not use these GICv2 features
that are not available in GICv1 Security Extension.

Change-Id: Ic2cb3055f1319a83455571d6d918661da583f179
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 14:42:06 +01:00
Etienne Carriere 634e4d2be6 aarch32: add missing dmb() macro
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 14:42:04 +01:00
Etienne Carriere ceada2b57e aarch32: add few missing weak platform specific function
Adds weak functions for plat_report_exception, bl1_plat_prepare_exit
and plat_error_handler in AArch32 mode.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 14:42:01 +01:00
Etienne Carriere 86e2683597 ARMv7 may not support Generic Timer Extension
If ARMv7 based platform does not set ARM_CORTEX_Ax=yes, platform
shall define ARMV7_SUPPORTS_GENERIC_TIMER to enable generic timer
support.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 14:41:47 +01:00
Etienne Carriere 64cc6e91e8 ARMv7 may not support Virtualization Extensions
ARMv7-A Virtualization extensions brings new instructions and resources
that were supported by later architectures. Reference ARM ARM Issue C.c
[DDI0406C_C].

ERET and extended MSR/MRS instructions, as specified in [DDI0406C_C] in
ID_PFR1 description of bits[15:12] (Virtualization Extensions):
 A value of 0b0001 implies implementation of the HVC, ERET, MRS
 (Banked register), and MSR (Banked register) instructions. The ID_ISARs
 do not identify whether these instructions are implemented.

UDIV/SDIV were introduced with the Virtualization extensions, even if
not strictly related to the virtualization extensions.

If ARMv7 based platform does not set ARM_CORTEX_Ax=yes, platform
shall define ARMV7_SUPPORTS_VIRTUALIZATION to enable virtualization
extension related resources.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 14:38:33 +01:00
Etienne Carriere 51b992ecec ARMv7 may not support large page addressing
ARCH_SUPPORTS_LARGE_PAGE_ADDRESSING allows build environment to
handle specific case when target ARMv7 core only supports 32bit MMU
descriptor mode.

If ARMv7 based platform does not set ARM_CORTEX_Ax=yes, platform
shall define ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING to enable
large page addressing support.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:53:47 +01:00
Etienne Carriere 1ca8d02316 ARMv7: introduce Cortex-A12
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:55 +01:00
Etienne Carriere 778e411dc9 ARMv7: introduce Cortex-A17
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:52 +01:00
Etienne Carriere 6ff43c2639 ARMv7: introduce Cortex-A7
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:49 +01:00
Etienne Carriere d56a846121 ARMv7: introduce Cortex-A5
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:45 +01:00
Etienne Carriere e3148c2b53 ARMv7: introduce Cortex-A9
As Cortex-A9 needs to manually enable program flow prediction,
do not reset SCTLR[Z] at entry. Platform should enable it only
once MMU is enabled.

Change-Id: I34e1ee2da73221903f7767f23bc6fc10ad01e3de
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:43 +01:00
Etienne Carriere 10922e7ade ARMv7: introduce Cortex-A15
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:40 +01:00
Etienne Carriere 94f4700017 ARMv7 architecture have specific system registers
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:36 +01:00
Etienne Carriere 908cf70597 ARMv7 does not support SDCR
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:32 +01:00
Etienne Carriere 0147bef523 ARMv7 does not support STL instruction
Also need to add a SEV instruction in ARMv7 spin_unlock which
is implicit in ARMv8.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:29 +01:00
Etienne Carriere 70896274ba ARMv7 requires the clear exclusive access at monitor entry
Clear exclusive monitor on SMC and FIQ entry for ARMv7 cores.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:49:12 +01:00
Etienne Carriere 26e63c4450 ARMv7 target is driven by ARM_ARCH_MAJOR==7
External build environment shall sets directive ARM_ARCH_MAJOR to 7
to specify a target ARMv7-A core.

As ARM-TF expects AARCH to be set, ARM_ARCH_MAJOR==7 mandates
AARCH=aarch32.

The toolchain target architecture/cpu is delegated after the platform
configuration is parsed. Platform shall define target core through
ARM_CORTEX_A<x>=yes, <x> being 5, 7, 9, 12, 15 and/or 17.

Platform can bypass ARM_CORTEX_A<x>=yes directive and provide straight
the toolchain target directive through MARCH32_DIRECTIVE.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-08 13:48:40 +01:00
davidcunado-arm 2904f84e3c
Merge pull request #1155 from masahir0y/uniphier
Fix build error when creating ROT key for UniPhier platform
2017-11-07 16:16:51 +00:00
Masahiro Yamada 3c9461520f uniphier: make sure to create build directory before ROT key
Building the UniPhier platform in parallel with TRUSTED_BOARD_BOOT=1
could fail due to non-existing directory.  It might be difficult to
reproduce, but here is an easier way to trigger the problem:

$ make PLAT=uniphier TRUSTED_BOARD_BOOT=1 MBEDTLS_DIR=mbedtls certificates
  OPENSSL build/uniphier/release/rot_key.pem
/bin/sh: 1: cannot create build/uniphier/release/rot_key.pem: Directory nonexistent
make: *** [build/uniphier/release/rot_key.pem] Error 2

The $(ROT_KEY) must depend on $(BUILD_PLAT) so that the build directory
is created before the key.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-11-07 00:35:21 +09:00
Masahiro Yamada 8012cc5c2f Build: introduce ${BUILD_PLAT} target to create the top build directory
Some platforms (for ex. UniPhier) want to create files in the very
top of the build directory.  Add ${BUILD_PLAT} so such files can
depend on it.

Make existing directory targets depend on ${BUILD_PLAT} because
they are sub-directories of ${BUILD_PLAT}.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
2017-11-07 00:35:21 +09:00
davidcunado-arm 92c5066c93
Merge pull request #1153 from robertovargas-arm/fix-macros
Avoid use of undefined macros
2017-11-06 13:59:42 +00:00
davidcunado-arm f9a6db0f48
Merge pull request #1151 from JoelHutton/jh/MISRA-Mandatory
Change sizeof to use type of struct not function
2017-11-03 20:59:57 +00:00
davidcunado-arm 157650c792
Merge pull request #1142 from etienne-lms/qemu-int
qemu: update deprecated interrupt registering
2017-11-03 16:27:42 +00:00
Soby Mathew bfc87a8dff Fix PSCI STAT time stamp collection
This patch includes various fixes for PSCI STAT functionality
relating to timestamp collection:

1. The PSCI stat accounting for retention states for higher level
power domains were done outside the locks which could lead to
spurious values in some race conditions. This is moved inside
the locks. Also, the call to start the stat accounting was redundant
which is now removed.

2. The timestamp wrap-around case when calculating residency did
not cater for AArch32. This is now fixed.

3. In the warm boot path, `plat_psci_stat_accounting_stop()` was
getting invoked prior to population of target power states. This
is now corrected.

Change-Id: I851526455304fb74ff0a724f4d5318cd89e19589
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
2017-11-03 13:27:34 +00:00
davidcunado-arm 3de7d58e61
Merge pull request #1137 from soby-mathew/sm/arm_plat_en_gicv3_save
Enable GICv3 save for ARM platforms
2017-11-03 13:12:48 +00:00
Etienne Carriere ad3803bfe7 qemu: update deprecated interrupt registering
Registered interrupts are configured in edge detection as the default
previous configuration assumed in previous code.

Not target mask required as Qemu BL31 will not send/route SGIs.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
2017-11-02 12:05:12 +01:00
davidcunado-arm 122af7dd6d
Merge pull request #1150 from dp-arm/dp/events
aarch64: Add PubSub events to capture security state transitions
2017-11-01 08:46:02 +00:00
Roberto Vargas e8a87acd4b Fix usage of IMAGE_BLx macros
These macros are only defined for corresponding image,
and they are undefined for other images. It means that we have
to use ifdef or defined() instead of relying on being 0 by default.

Change-Id: Iad11efab9830ddf471599b46286e1c56581ef5a7
Signed-off-by: Roberto Vargas <roberto.vargas@arm.com>
2017-11-01 08:28:04 +00:00