From e8530033b8b5a353c884fd3c90457f703ff0bc38 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sat, 14 Jun 2014 00:00:10 +0100 Subject: arch/mips: Add base MIPS architecture support Add the build infrastructure and basic architectural support required to build for targets using the MIPS architecture. This is sufficient to run on a simulator, but will require the addition of some cache maintenance and timer setup in order to run on real hardware. BUG=chrome-os-partner:31438, chromium:409082 TEST=none yet Change-Id: I027902d8408e419b626d0aab7768bc564bd49047 Signed-off-by: Patrick Georgi Original-Commit-Id: fcc0d934d7223922c878b1f87021cb5c2d7e6f21 Original-Change-Id: If4f99554463bd3760fc142477440326fd16c67cc Original-Signed-off-by: Paul Burton Original-Signed-off-by: Vadim Bendebury Original-Reviewed-on: https://chromium-review.googlesource.com/207972 Original-Reviewed-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/8760 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/arch/mips/include/arch/byteorder.h | 48 ++++++++++ src/arch/mips/include/arch/cache.h | 23 +++++ src/arch/mips/include/arch/cpu.h | 43 +++++++++ src/arch/mips/include/arch/early_variables.h | 30 +++++++ src/arch/mips/include/arch/exception.h | 25 ++++++ src/arch/mips/include/arch/hlt.h | 29 +++++++ src/arch/mips/include/arch/io.h | 125 +++++++++++++++++++++++++++ src/arch/mips/include/arch/pci_ops.h | 30 +++++++ src/arch/mips/include/arch/stages.h | 29 +++++++ src/arch/mips/include/arch/types.h | 67 ++++++++++++++ src/arch/mips/include/bootblock_common.h | 30 +++++++ src/arch/mips/include/stdint.h | 99 +++++++++++++++++++++ 12 files changed, 578 insertions(+) create mode 100644 src/arch/mips/include/arch/byteorder.h create mode 100644 src/arch/mips/include/arch/cache.h create mode 100644 src/arch/mips/include/arch/cpu.h create mode 100644 src/arch/mips/include/arch/early_variables.h create mode 100644 src/arch/mips/include/arch/exception.h create mode 100644 src/arch/mips/include/arch/hlt.h create mode 100644 src/arch/mips/include/arch/io.h create mode 100644 src/arch/mips/include/arch/pci_ops.h create mode 100644 src/arch/mips/include/arch/stages.h create mode 100644 src/arch/mips/include/arch/types.h create mode 100644 src/arch/mips/include/bootblock_common.h create mode 100644 src/arch/mips/include/stdint.h (limited to 'src/arch/mips/include') diff --git a/src/arch/mips/include/arch/byteorder.h b/src/arch/mips/include/arch/byteorder.h new file mode 100644 index 0000000000..90c375e691 --- /dev/null +++ b/src/arch/mips/include/arch/byteorder.h @@ -0,0 +1,48 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_BYTEORDER_H +#define __MIPS_ARCH_BYTEORDER_H + +#include +#include + +#ifndef __ORDER_LITTLE_ENDIAN__ +#errror "What endian are you!?" +#endif + +#define cpu_to_le64(x) ((uint64_t)(x)) +#define le64_to_cpu(x) ((uint64_t)(x)) +#define cpu_to_le32(x) ((uint32_t)(x)) +#define le32_to_cpu(x) ((uint32_t)(x)) +#define cpu_to_le16(x) ((uint16_t)(x)) +#define le16_to_cpu(x) ((uint16_t)(x)) +#define cpu_to_be64(x) swab64(x) +#define be64_to_cpu(x) swab64(x) +#define cpu_to_be32(x) swab32((x)) +#define be32_to_cpu(x) swab32((x)) +#define cpu_to_be16(x) swab16((x)) +#define be16_to_cpu(x) swab16((x)) + +#define ntohll(x) be64_to_cpu(x) +#define htonll(x) cpu_to_be64(x) +#define ntohl(x) be32_to_cpu(x) +#define htonl(x) cpu_to_be32(x) + +#endif /* __MIPS_ARCH_BYTEORDER_H */ diff --git a/src/arch/mips/include/arch/cache.h b/src/arch/mips/include/arch/cache.h new file mode 100644 index 0000000000..a9857414ce --- /dev/null +++ b/src/arch/mips/include/arch/cache.h @@ -0,0 +1,23 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_CACHE_H +#define __MIPS_ARCH_CACHE_H + +#endif /* __MIPS_ARCH_CACHE_H */ diff --git a/src/arch/mips/include/arch/cpu.h b/src/arch/mips/include/arch/cpu.h new file mode 100644 index 0000000000..0ac9f31700 --- /dev/null +++ b/src/arch/mips/include/arch/cpu.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_CPU_H +#define __MIPS_ARCH_CPU_H + +#define asmlinkage + +#ifndef __PRE_RAM__ + +#include + +struct cpu_driver { + struct device_operations *ops; + struct cpu_device_id *id_table; +}; + +struct thread; + +struct cpu_info { + device_t cpu; + unsigned long index; +}; + +#endif /* !__PRE_RAM__ */ + +#endif /* __MIPS_ARCH_CPU_H */ diff --git a/src/arch/mips/include/arch/early_variables.h b/src/arch/mips/include/arch/early_variables.h new file mode 100644 index 0000000000..a81a6b4037 --- /dev/null +++ b/src/arch/mips/include/arch/early_variables.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_EARLY_VARIABLES_H +#define __MIPS_ARCH_EARLY_VARIABLES_H + +#define CAR_GLOBAL +#define CAR_MIGRATE(migrate_fn_) + +static inline void car_migrate_variables(void) {} +#define car_get_var(var) (var) +#define car_set_var(var, val) { (var) = (val); } + +#endif /* __MIPS_ARCH_EARLY_VARIABLES_H */ diff --git a/src/arch/mips/include/arch/exception.h b/src/arch/mips/include/arch/exception.h new file mode 100644 index 0000000000..ff92728005 --- /dev/null +++ b/src/arch/mips/include/arch/exception.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_EXCEPTION_H +#define __MIPS_ARCH_EXCEPTION_H + +static inline void exception_init(void) {} + +#endif /* __MIPS_ARCH_EXCEPTION_H */ diff --git a/src/arch/mips/include/arch/hlt.h b/src/arch/mips/include/arch/hlt.h new file mode 100644 index 0000000000..851de56556 --- /dev/null +++ b/src/arch/mips/include/arch/hlt.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_HLT_H +#define __MIPS_ARCH_HLT_H + +static inline __attribute__((always_inline)) void hlt(void) +{ + for (;;) + ; +} + +#endif /* __MIPS_ARCH_HLT_H */ diff --git a/src/arch/mips/include/arch/io.h b/src/arch/mips/include/arch/io.h new file mode 100644 index 0000000000..d034b09dc5 --- /dev/null +++ b/src/arch/mips/include/arch/io.h @@ -0,0 +1,125 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * Based on arch/armv7/include/arch/io.h: + * Copyright 2013 Google Inc. + * Copyright (C) 1996-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_IO_H +#define __MIPS_ARCH_IO_H + +#include +#include +#include + +static inline uint8_t read8(unsigned long addr) +{ + asm("sync"); + return *(volatile uint8_t *)addr; +} + +static inline uint16_t read16(unsigned long addr) +{ + asm("sync"); + return *(volatile uint16_t *)addr; +} + +static inline uint32_t read32(unsigned long addr) +{ + asm("sync"); + return *(volatile uint32_t *)addr; +} + +static inline void write8(unsigned long addr, uint8_t val) +{ + asm("sync"); + *(volatile uint8_t *)addr = val; + asm("sync"); +} + +static inline void write16(unsigned long addr, uint16_t val) +{ + asm("sync"); + *(volatile uint16_t *)addr = val; + asm("sync"); +} + +static inline void write32(unsigned long addr, uint32_t val) +{ + asm("sync"); + *(volatile uint32_t *)addr = val; + asm("sync"); +} + +/* + * Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define out_arch(type, endian, a, v) write##type(cpu_to_##endian(v), a) +#define in_arch(type, endian, a) endian##_to_cpu(read##type(a)) + +#define out_le32(a, v) out_arch(l, le32, a, v) +#define out_le16(a, v) out_arch(w, le16, a, v) + +#define in_le32(a) in_arch(l, le32, a) +#define in_le16(a) in_arch(w, le16, a) + +#define out_be32(a, v) out_arch(l, be32, a, v) +#define out_be16(a, v) out_arch(w, be16, a, v) + +#define in_be32(a) in_arch(l, be32, a) +#define in_be16(a) in_arch(w, be16, a) + +#define out_8(a, v) writeb(v, a) +#define in_8(a) readb(a) + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + +#endif /* __MIPS_ARCH_IO_H */ diff --git a/src/arch/mips/include/arch/pci_ops.h b/src/arch/mips/include/arch/pci_ops.h new file mode 100644 index 0000000000..1b3f07417b --- /dev/null +++ b/src/arch/mips/include/arch/pci_ops.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ARCH_MIPS_PCI_OPS_H +#define ARCH_MIPS_PCI_OPS_H + +#include + +static inline const struct pci_bus_operations *pci_config_default(void) +{ + return NULL; +} + +#endif diff --git a/src/arch/mips/include/arch/stages.h b/src/arch/mips/include/arch/stages.h new file mode 100644 index 0000000000..b95ad1db4f --- /dev/null +++ b/src/arch/mips/include/arch/stages.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_STAGES_H +#define __MIPS_ARCH_STAGES_H + +extern void main(void); + +void stage_entry(void); +void stage_exit(void *); +void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size); + +#endif /* __MIPS_ARCH_STAGES_H */ diff --git a/src/arch/mips/include/arch/types.h b/src/arch/mips/include/arch/types.h new file mode 100644 index 0000000000..c3eae24e09 --- /dev/null +++ b/src/arch/mips/include/arch/types.h @@ -0,0 +1,67 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * Based on src/arch/armv7/include/arch/types.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_ARCH_TYPES_H +#define __MIPS_ARCH_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) +__extension__ typedef __signed__ long long __s64; +__extension__ typedef unsigned long long __u64; +#endif + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +typedef unsigned long phys_addr_t; +typedef unsigned long phys_size_t; + +#endif /* __MIPS_ARCH_TYPES_H */ diff --git a/src/arch/mips/include/bootblock_common.h b/src/arch/mips/include/bootblock_common.h new file mode 100644 index 0000000000..e1960ba6a4 --- /dev/null +++ b/src/arch/mips/include/bootblock_common.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Imagination Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef CONFIG_BOOTBLOCK_CPU_INIT +#include CONFIG_BOOTBLOCK_CPU_INIT +#endif + +#ifdef CONFIG_BOOTBLOCK_MAINBOARD_INIT +#include CONFIG_BOOTBLOCK_MAINBOARD_INIT +#else +static void bootblock_mainboard_init(void) +{ +} +#endif diff --git a/src/arch/mips/include/stdint.h b/src/arch/mips/include/stdint.h new file mode 100644 index 0000000000..5c21fe6742 --- /dev/null +++ b/src/arch/mips/include/stdint.h @@ -0,0 +1,99 @@ +/* + * This file is part of the coreboot project. + * + * Based on src/arch/armv7/include/stdint.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MIPS_STDINT_H +#define __MIPS_STDINT_H + +#if defined(__GNUC__) +#define __HAVE_LONG_LONG__ 1 +#else +#define __HAVE_LONG_LONG__ 0 +#endif + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +#endif + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; +#endif + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; +#endif + +/* Types for `void *' pointers. */ +typedef int intptr_t; +typedef unsigned int uintptr_t; + +/* Largest integral types */ +#if __HAVE_LONG_LONG__ +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; +#else +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +#endif + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#if __HAVE_LONG_LONG__ +typedef uint64_t u64; +#endif +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; + +#undef __HAVE_LONG_LONG__ + +#endif /* __MIPS_STDINT_H */ -- cgit v1.2.3