11156bde8d
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmFK++oACgkQONu9yGCS aT7Rjw/9GSgR6XM8TwZiL7JVTQQPHxKOILQA2LCrPVGDFadxfUfdHENAhp8cWzTS u0TTMJdMa1/gRyj6BaIHH7bUj9IJhQ8Y/iE0ySQCCD3yQKvY9pnCX/vzsbVC5NzX 6oiooirU0Fzj4/F6G2aq7pNUdi+nUpTIZj8SznJJYfdfFNEH5cPM1E1OL9QgbyaQ 6ziQMUZfnt6s5me2sldboqbhmaQK8Dew+P+0BWnE1bDNCWQkPCG/0u62gRDnzHn2 5+pQPRnkS0ruVWlFswEcIsSb59GywJiINodLKcBvPZdjNJO+zmuXMGs0C6OuwoUd RgLFB76BfmdIroyp+6EuXCcmAo0N4hd8yoETY11LdgygoeNGJPBFHBYGGt2v5YFf Ge2iR8PuR7AGtbwEcpnJnjBa6Kpftrqolz2fw8LIdVwr5CORQ0p9KYGbwY4tT3p1 hGTEdJAIGpEqrjl2m2mpIeRlWRYNzIJRjdH2PLrdulwoJw0rlVfE24O4BK0sCcz5 Z+lUkLMIYPdmQETgKRyYGubzZ0wP8Iyd9JrHcIu5AH+IBKpawyzKpj3jk81vAIpq Wzay+7eK6TcDkd/0cnE/5OsY20OMrecjRaw/XK79FnSFFRGtv6tlhFU4EYSbvjYp z6d6OCtTH3220dDUrnaqVLooInocVp2Hn8+x1pjM3C0sTUjfBYo= =Gz7W -----END PGP SIGNATURE----- Merge 4.19.207 into android-4.19-stable Changes in 4.19.207 ext4: fix race writing to an inline_data file while its xattrs are changing xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG gpu: ipu-v3: Fix i.MX IPU-v3 offset calculations for (semi)planar U/V formats qed: Fix the VF msix vectors flow net: macb: Add a NULL check on desc_ptp qede: Fix memset corruption perf/x86/intel/pt: Fix mask of num_address_ranges perf/x86/amd/ibs: Work around erratum #1197 cryptoloop: add a deprecation warning ARM: 8918/2: only build return_address() if needed ALSA: pcm: fix divide error in snd_pcm_lib_ioctl clk: fix build warning for orphan_list media: stkwebcam: fix memory leak in stk_camera_probe ARM: imx: add missing clk_disable_unprepare() ARM: imx: fix missing 3rd argument in macro imx_mmdc_perf_init igmp: Add ip_mc_list lock in ip_check_mc_rcu USB: serial: mos7720: improve OOM-handling in read_mos_reg() ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing table (v2) SUNRPC/nfs: Fix return value for nfs4_callback_compound() crypto: talitos - reduce max key size for SEC1 powerpc/module64: Fix comment in R_PPC64_ENTRY handling powerpc/boot: Delete unneeded .globl _zimage_start net: ll_temac: Remove left-over debug message mm/page_alloc: speed up the iteration of max_order Revert "btrfs: compression: don't try to compress if we don't have enough pages" ALSA: usb-audio: Add registration quirk for JBL Quantum 800 usb: host: xhci-rcar: Don't reload firmware after the completion usb: mtu3: use @mult for HS isoc or intr usb: mtu3: fix the wrong HS mult value x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions PCI: Call Max Payload Size-related fixup quirks early locking/mutex: Fix HANDOFF condition regmap: fix the offset of register error log crypto: mxs-dcp - Check for DMA mapping errors sched/deadline: Fix reset_on_fork reporting of DL tasks power: supply: axp288_fuel_gauge: Report register-address on readb / writeb errors crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop() sched/deadline: Fix missing clock update in migrate_task_rq_dl() hrtimer: Avoid double reprogramming in __hrtimer_start_range_ns() udf: Check LVID earlier isofs: joliet: Fix iocharset=utf8 mount option bcache: add proper error unwinding in bcache_device_init nvme-rdma: don't update queue count when failing to set io queues power: supply: max17042_battery: fix typo in MAx17042_TOFF s390/cio: add dev_busid sysfs entry for each subchannel libata: fix ata_host_start() crypto: qat - do not ignore errors from enable_vf2pf_comms() crypto: qat - handle both source of interrupt in VF ISR crypto: qat - fix reuse of completion variable crypto: qat - fix naming for init/shutdown VF to PF notifications crypto: qat - do not export adf_iov_putmsg() fcntl: fix potential deadlock for &fasync_struct.fa_lock udf_get_extendedattr() had no boundary checks. m68k: emu: Fix invalid free in nfeth_cleanup() spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_config spi: spi-pic32: Fix issue with uninitialized dma_slave_config lib/mpi: use kcalloc in mpi_resize clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock source channel crypto: qat - use proper type for vf_mask certs: Trigger creation of RSA module signing key if it's not an RSA key spi: sprd: Fix the wrong WDG_LOAD_VAL media: TDA1997x: enable EDID support soc: rockchip: ROCKCHIP_GRF should not default to y, unconditionally media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init media: dvb-usb: fix uninit-value in vp702x_read_mac_addr media: go7007: remove redundant initialization Bluetooth: sco: prevent information leak in sco_conn_defer_accept() tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos net: cipso: fix warnings in netlbl_cipsov4_add_std i2c: highlander: add IRQ check media: em28xx-input: fix refcount bug in em28xx_usb_disconnect media: venus: venc: Fix potential null pointer dereference on pointer fmt PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently PCI: PM: Enable PME if it can be signaled from D3cold soc: qcom: smsm: Fix missed interrupts if state changes while masked Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow drm/msm/dpu: make dpu_hw_ctl_clear_all_blendstages clear necessary LMs arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7 Bluetooth: fix repeated calls to sco_sock_kill drm/msm/dsi: Fix some reference counted resource leaks usb: gadget: udc: at91: add IRQ check usb: phy: fsl-usb: add IRQ check usb: phy: twl6030: add IRQ checks Bluetooth: Move shutdown callback before flushing tx and rx queue usb: host: ohci-tmio: add IRQ check usb: phy: tahvo: add IRQ check mac80211: Fix insufficient headroom issue for AMSDU usb: gadget: mv_u3d: request_irq() after initializing UDC Bluetooth: add timeout sanity check to hci_inquiry i2c: iop3xx: fix deferred probing i2c: s3c2410: fix IRQ check mmc: dw_mmc: Fix issue with uninitialized dma_slave_config mmc: moxart: Fix issue with uninitialized dma_slave_config CIFS: Fix a potencially linear read overflow i2c: mt65xx: fix IRQ check usb: ehci-orion: Handle errors of clk_prepare_enable() in probe usb: bdc: Fix an error handling path in 'bdc_probe()' when no suitable DMA config is available tty: serial: fsl_lpuart: fix the wrong mapbase value ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point() bcma: Fix memory leak for internally-handled cores ipv4: make exception cache less predictible net: sched: Fix qdisc_rate_table refcount leak when get tcf_block failed net: qualcomm: fix QCA7000 checksum handling ipv4: fix endianness issue in inet_rtm_getroute_build_skb() netns: protect netns ID lookups with RCU fscrypt: add fscrypt_symlink_getattr() for computing st_size ext4: report correct st_size for encrypted symlinks f2fs: report correct st_size for encrypted symlinks ubifs: report correct st_size for encrypted symlinks tty: Fix data race between tiocsti() and flush_to_ldisc() x86/resctrl: Fix a maybe-uninitialized build warning treated as error KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is adjusted IMA: remove -Wmissing-prototypes warning IMA: remove the dependency on CRYPTO_MD5 fbmem: don't allow too huge resolutions backlight: pwm_bl: Improve bootloader/kernel device handover clk: kirkwood: Fix a clocking boot regression rtc: tps65910: Correct driver module alias btrfs: reset replace target device to allocation state on close blk-zoned: allow zone management send operations without CAP_SYS_ADMIN blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN PCI/MSI: Skip masking MSI-X on Xen PV powerpc/perf/hv-gpci: Fix counter value parsing xen: fix setting of max_pfn in shared_info include/linux/list.h: add a macro to test if entry is pointing to the head 9p/xen: Fix end of loop tests for list_for_each_entry bpf/verifier: per-register parent pointers bpf: correct slot_type marking logic to allow more stack slot sharing bpf: Support variable offset stack access from helpers bpf: Reject indirect var_off stack access in raw mode bpf: Reject indirect var_off stack access in unpriv mode bpf: Sanity check max value for var_off stack access selftests/bpf: Test variable offset stack access bpf: track spill/fill of constants selftests/bpf: fix tests due to const spill/fill bpf: Introduce BPF nospec instruction for mitigating Spectre v4 bpf: Fix leakage due to insufficient speculative store bypass mitigation bpf: verifier: Allocate idmap scratch in verifier env bpf: Fix pointer arithmetic mask tightening under state pruning tools/thermal/tmon: Add cross compiling support soc: aspeed: lpc-ctrl: Fix boundary check for mmap arm64: head: avoid over-mapping in map_memory crypto: public_key: fix overflow during implicit conversion block: bfq: fix bfq_set_next_ioprio_data() power: supply: max17042: handle fails of reading status register dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc() VMCI: fix NULL pointer dereference when unmapping queue pair media: uvc: don't do DMA on stack media: rc-loopback: return number of emitters rather than error libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs ARM: 9105/1: atags_to_fdt: don't warn about stack size PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure PCI: xilinx-nwl: Enable the clock through CCF PCI: aardvark: Increase polling delay to 1.5s while waiting for PIO response PCI: aardvark: Fix masking and unmasking legacy INTx interrupts HID: input: do not report stylus battery state as "full" RDMA/iwcm: Release resources if iw_cm module initialization fails docs: Fix infiniband uverbs minor number pinctrl: samsung: Fix pinctrl bank pin count vfio: Use config not menuconfig for VFIO_NOIOMMU powerpc/stacktrace: Include linux/delay.h openrisc: don't printk() unconditionally pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry() scsi: qedi: Fix error codes in qedi_alloc_global_queues() platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from run_smbios_call fscache: Fix cookie key hashing f2fs: fix to account missing .skipped_gc_rwsem f2fs: fix to unmap pages from userspace process in punch_hole() MIPS: Malta: fix alignment of the devicetree buffer userfaultfd: prevent concurrent API initialization media: dib8000: rewrite the init prbs logic crypto: mxs-dcp - Use sg_mapping_iter to copy data PCI: Use pci_update_current_state() in pci_enable_device_flags() tipc: keep the skb in rcv queue until the whole data is read iio: dac: ad5624r: Fix incorrect handling of an optional regulator. ARM: dts: qcom: apq8064: correct clock names video: fbdev: kyro: fix a DoS bug by restricting user input netlink: Deal with ESRCH error in nlmsg_notify() Smack: Fix wrong semantics in smk_access_entry() usb: host: fotg210: fix the endpoint's transactional opportunities calculation usb: host: fotg210: fix the actual_length of an iso packet usb: gadget: u_ether: fix a potential null pointer dereference usb: gadget: composite: Allow bMaxPower=0 if self-powered staging: board: Fix uninitialized spinlock when attaching genpd tty: serial: jsm: hold port lock when reporting modem line changes drm/amd/amdgpu: Update debugfs link_settings output link_rate field in hex bpf/tests: Fix copy-and-paste error in double word test bpf/tests: Do not PASS tests without actually testing the result video: fbdev: asiliantfb: Error out if 'pixclock' equals zero video: fbdev: kyro: Error out if 'pixclock' equals zero video: fbdev: riva: Error out if 'pixclock' equals zero ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs() flow_dissector: Fix out-of-bounds warnings s390/jump_label: print real address in a case of a jump label bug serial: 8250: Define RX trigger levels for OxSemi 950 devices xtensa: ISS: don't panic in rs_init hvsi: don't panic on tty_register_driver failure serial: 8250_pci: make setup_port() parameters explicitly unsigned staging: ks7010: Fix the initialization of the 'sleep_status' structure samples: bpf: Fix tracex7 error raised on the missing argument ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init() Bluetooth: skip invalid hci_sync_conn_complete_evt bonding: 3ad: fix the concurrency between __bond_release_one() and bond_3ad_state_machine_handler() ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the matching in-/output media: imx258: Rectify mismatch of VTS value media: imx258: Limit the max analogue gain to 480 media: v4l2-dv-timings.c: fix wrong condition in two for-loops media: TDA1997x: fix tda1997x_query_dv_timings() return value media: tegra-cec: Handle errors of clk_prepare_enable() ARM: dts: imx53-ppd: Fix ACHC entry arm64: dts: qcom: sdm660: use reg value for memory node net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe() Bluetooth: schedule SCO timeouts with delayed_work Bluetooth: avoid circular locks in sco_sock_connect gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable access in amdgpu_i2c_router_select_ddc_port() ARM: tegra: tamonten: Fix UART pad setting Bluetooth: Fix handling of LE Enhanced Connection Complete serial: sh-sci: fix break handling for sysrq tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD rpc: fix gss_svc_init cleanup on failure staging: rts5208: Fix get_ms_information() heap buffer size gfs2: Don't call dlm after protocol is unmounted of: Don't allow __of_attached_node_sysfs() without CONFIG_SYSFS mmc: sdhci-of-arasan: Check return value of non-void funtions mmc: rtsx_pci: Fix long reads when clock is prescaled selftests/bpf: Enlarge select() timeout for test_maps mmc: core: Return correct emmc response in case of ioctl error cifs: fix wrong release in sess_alloc_buffer() failed path Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set" usb: musb: musb_dsps: request_irq() after initializing musb usbip: give back URBs for unsent unlink requests during cleanup usbip:vhci_hcd USB port can get stuck in the disabled state ASoC: rockchip: i2s: Fix regmap_ops hang ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B parport: remove non-zero check on count ath9k: fix OOB read ar9300_eeprom_restore_internal ath9k: fix sleeping in atomic context net: fix NULL pointer reference in cipso_v4_doi_free net: w5100: check return value after calling platform_get_resource() parisc: fix crash with signals and alloca ovl: fix BUG_ON() in may_delete() when called from ovl_cleanup() scsi: BusLogic: Fix missing pr_cont() use scsi: qla2xxx: Sync queue idx with queue_pair_map idx cpufreq: powernv: Fix init_chip_info initialization in numa=off mm/hugetlb: initialize hugetlb_usage in mm_init memcg: enable accounting for pids in nested pid namespaces platform/chrome: cros_ec_proto: Send command again when timeout occurs drm/amdgpu: Fix BUG_ON assert dm thin metadata: Fix use-after-free in dm_bm_set_read_only xen: reset legacy rtc flag for PV domU bnx2x: Fix enabling network interfaces without VFs arm64/sve: Use correct size when reinitialising SVE state PM: base: power: don't try to use non-existing RTC for storing data PCI: Add AMD GPU multi-function power dependencies x86/mm: Fix kern_addr_valid() to cope with existing but not present entries tipc: fix an use-after-free issue in tipc_recvmsg net-caif: avoid user-triggerable WARN_ON(1) ptp: dp83640: don't define PAGE0 dccp: don't duplicate ccid when cloning dccp sock net/l2tp: Fix reference count leak in l2tp_udp_recv_core r6040: Restore MDIO clock frequency after MAC reset tipc: increase timeout in tipc_sk_enqueue() perf machine: Initialize srcline string member in add_location struct net/mlx5: Fix potential sleeping in atomic context events: Reuse value read using READ_ONCE instead of re-reading it net/af_unix: fix a data-race in unix_dgram_poll net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup tcp: fix tp->undo_retrans accounting in tcp_sacktag_one() qed: Handle management FW error ibmvnic: check failover_pending in login response net: hns3: pad the short tunnel frame before sending to hardware mm/memory_hotplug: use "unsigned long" for PFN in zone_for_pfn_range() KVM: s390: index kvm->arch.idle_mask by vcpu_idx dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation mfd: Don't use irq_create_mapping() to resolve a mapping PCI: Add ACS quirks for Cavium multi-function devices net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920 block, bfq: honor already-setup queue merges ethtool: Fix an error code in cxgb2.c NTB: perf: Fix an error code in perf_setup_inbuf() mfd: axp20x: Update AXP288 volatile ranges PCI: Fix pci_dev_str_match_path() alloc while atomic bug KVM: arm64: Handle PSCI resets before userspace touches vCPU state PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n mtd: rawnand: cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()' ARC: export clear_user_page() for modules net: dsa: b53: Fix calculating number of switch ports netfilter: socket: icmp6: fix use-after-scope fq_codel: reject silly quantum parameters qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom ip_gre: validate csum_start only on pull net: renesas: sh_eth: Fix freeing wrong tx descriptor s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant Linux 4.19.207 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I18108cb47ba9e95838ebe55aaabe34de345ee846
979 lines
27 KiB
ArmAsm
979 lines
27 KiB
ArmAsm
/*
|
|
* Low-level CPU initialisation
|
|
* Based on arch/arm/kernel/head.S
|
|
*
|
|
* Copyright (C) 1994-2002 Russell King
|
|
* Copyright (C) 2003-2012 ARM Ltd.
|
|
* Authors: Catalin Marinas <catalin.marinas@arm.com>
|
|
* Will Deacon <will.deacon@arm.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <linux/init.h>
|
|
#include <linux/irqchip/arm-gic-v3.h>
|
|
|
|
#include <asm/assembler.h>
|
|
#include <asm/boot.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/cache.h>
|
|
#include <asm/cputype.h>
|
|
#include <asm/elf.h>
|
|
#include <asm/kernel-pgtable.h>
|
|
#include <asm/kvm_arm.h>
|
|
#include <asm/memory.h>
|
|
#include <asm/pgtable-hwdef.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/page.h>
|
|
#include <asm/scs.h>
|
|
#include <asm/smp.h>
|
|
#include <asm/sysreg.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/virt.h>
|
|
|
|
#include "efi-header.S"
|
|
|
|
#define __PHYS_OFFSET (KERNEL_START - TEXT_OFFSET)
|
|
|
|
#if (TEXT_OFFSET & 0xfff) != 0
|
|
#error TEXT_OFFSET must be at least 4KB aligned
|
|
#elif (PAGE_OFFSET & 0x1fffff) != 0
|
|
#error PAGE_OFFSET must be at least 2MB aligned
|
|
#elif TEXT_OFFSET > 0x1fffff
|
|
#error TEXT_OFFSET must be less than 2MB
|
|
#endif
|
|
|
|
/*
|
|
* Kernel startup entry point.
|
|
* ---------------------------
|
|
*
|
|
* The requirements are:
|
|
* MMU = off, D-cache = off, I-cache = on or off,
|
|
* x0 = physical address to the FDT blob.
|
|
*
|
|
* This code is mostly position independent so you call this at
|
|
* __pa(PAGE_OFFSET + TEXT_OFFSET).
|
|
*
|
|
* Note that the callee-saved registers are used for storing variables
|
|
* that are useful before the MMU is enabled. The allocations are described
|
|
* in the entry routines.
|
|
*/
|
|
__HEAD
|
|
_head:
|
|
/*
|
|
* DO NOT MODIFY. Image header expected by Linux boot-loaders.
|
|
*/
|
|
#ifdef CONFIG_EFI
|
|
/*
|
|
* This add instruction has no meaningful effect except that
|
|
* its opcode forms the magic "MZ" signature required by UEFI.
|
|
*/
|
|
add x13, x18, #0x16
|
|
b stext
|
|
#else
|
|
b stext // branch to kernel start, magic
|
|
.long 0 // reserved
|
|
#endif
|
|
le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian
|
|
le64sym _kernel_size_le // Effective size of kernel image, little-endian
|
|
le64sym _kernel_flags_le // Informative flags, little-endian
|
|
.quad 0 // reserved
|
|
.quad 0 // reserved
|
|
.quad 0 // reserved
|
|
.ascii "ARM\x64" // Magic number
|
|
#ifdef CONFIG_EFI
|
|
.long pe_header - _head // Offset to the PE header.
|
|
|
|
pe_header:
|
|
__EFI_PE_HEADER
|
|
#else
|
|
.long 0 // reserved
|
|
#endif
|
|
|
|
__INIT
|
|
|
|
/*
|
|
* The following callee saved general purpose registers are used on the
|
|
* primary lowlevel boot path:
|
|
*
|
|
* Register Scope Purpose
|
|
* x21 stext() .. start_kernel() FDT pointer passed at boot in x0
|
|
* x23 stext() .. start_kernel() physical misalignment/KASLR offset
|
|
* x28 __create_page_tables() callee preserved temp register
|
|
* x19/x20 __primary_switch() callee preserved temp registers
|
|
* x24 __primary_switch() .. relocate_kernel()
|
|
* current RELR displacement
|
|
*/
|
|
ENTRY(stext)
|
|
bl preserve_boot_args
|
|
bl el2_setup // Drop to EL1, w0=cpu_boot_mode
|
|
adrp x23, __PHYS_OFFSET
|
|
and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0
|
|
bl set_cpu_boot_mode_flag
|
|
bl __create_page_tables
|
|
/*
|
|
* The following calls CPU setup code, see arch/arm64/mm/proc.S for
|
|
* details.
|
|
* On return, the CPU will be ready for the MMU to be turned on and
|
|
* the TCR will have been set.
|
|
*/
|
|
bl __cpu_setup // initialise processor
|
|
b __primary_switch
|
|
ENDPROC(stext)
|
|
|
|
/*
|
|
* Preserve the arguments passed by the bootloader in x0 .. x3
|
|
*/
|
|
preserve_boot_args:
|
|
mov x21, x0 // x21=FDT
|
|
|
|
adr_l x0, boot_args // record the contents of
|
|
stp x21, x1, [x0] // x0 .. x3 at kernel entry
|
|
stp x2, x3, [x0, #16]
|
|
|
|
dmb sy // needed before dc ivac with
|
|
// MMU off
|
|
|
|
mov x1, #0x20 // 4 x 8 bytes
|
|
b __inval_dcache_area // tail call
|
|
ENDPROC(preserve_boot_args)
|
|
|
|
/*
|
|
* Macro to create a table entry to the next page.
|
|
*
|
|
* tbl: page table address
|
|
* virt: virtual address
|
|
* shift: #imm page table shift
|
|
* ptrs: #imm pointers per table page
|
|
*
|
|
* Preserves: virt
|
|
* Corrupts: ptrs, tmp1, tmp2
|
|
* Returns: tbl -> next level table page address
|
|
*/
|
|
.macro create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
|
|
add \tmp1, \tbl, #PAGE_SIZE
|
|
phys_to_pte \tmp2, \tmp1
|
|
orr \tmp2, \tmp2, #PMD_TYPE_TABLE // address of next table and entry type
|
|
lsr \tmp1, \virt, #\shift
|
|
sub \ptrs, \ptrs, #1
|
|
and \tmp1, \tmp1, \ptrs // table index
|
|
str \tmp2, [\tbl, \tmp1, lsl #3]
|
|
add \tbl, \tbl, #PAGE_SIZE // next level table page
|
|
.endm
|
|
|
|
/*
|
|
* Macro to populate page table entries, these entries can be pointers to the next level
|
|
* or last level entries pointing to physical memory.
|
|
*
|
|
* tbl: page table address
|
|
* rtbl: pointer to page table or physical memory
|
|
* index: start index to write
|
|
* eindex: end index to write - [index, eindex] written to
|
|
* flags: flags for pagetable entry to or in
|
|
* inc: increment to rtbl between each entry
|
|
* tmp1: temporary variable
|
|
*
|
|
* Preserves: tbl, eindex, flags, inc
|
|
* Corrupts: index, tmp1
|
|
* Returns: rtbl
|
|
*/
|
|
.macro populate_entries, tbl, rtbl, index, eindex, flags, inc, tmp1
|
|
.Lpe\@: phys_to_pte \tmp1, \rtbl
|
|
orr \tmp1, \tmp1, \flags // tmp1 = table entry
|
|
str \tmp1, [\tbl, \index, lsl #3]
|
|
add \rtbl, \rtbl, \inc // rtbl = pa next level
|
|
add \index, \index, #1
|
|
cmp \index, \eindex
|
|
b.ls .Lpe\@
|
|
.endm
|
|
|
|
/*
|
|
* Compute indices of table entries from virtual address range. If multiple entries
|
|
* were needed in the previous page table level then the next page table level is assumed
|
|
* to be composed of multiple pages. (This effectively scales the end index).
|
|
*
|
|
* vstart: virtual address of start of range
|
|
* vend: virtual address of end of range - we map [vstart, vend]
|
|
* shift: shift used to transform virtual address into index
|
|
* ptrs: number of entries in page table
|
|
* istart: index in table corresponding to vstart
|
|
* iend: index in table corresponding to vend
|
|
* count: On entry: how many extra entries were required in previous level, scales
|
|
* our end index.
|
|
* On exit: returns how many extra entries required for next page table level
|
|
*
|
|
* Preserves: vstart, vend, shift, ptrs
|
|
* Returns: istart, iend, count
|
|
*/
|
|
.macro compute_indices, vstart, vend, shift, ptrs, istart, iend, count
|
|
lsr \iend, \vend, \shift
|
|
mov \istart, \ptrs
|
|
sub \istart, \istart, #1
|
|
and \iend, \iend, \istart // iend = (vend >> shift) & (ptrs - 1)
|
|
mov \istart, \ptrs
|
|
mul \istart, \istart, \count
|
|
add \iend, \iend, \istart // iend += (count - 1) * ptrs
|
|
// our entries span multiple tables
|
|
|
|
lsr \istart, \vstart, \shift
|
|
mov \count, \ptrs
|
|
sub \count, \count, #1
|
|
and \istart, \istart, \count
|
|
|
|
sub \count, \iend, \istart
|
|
.endm
|
|
|
|
/*
|
|
* Map memory for specified virtual address range. Each level of page table needed supports
|
|
* multiple entries. If a level requires n entries the next page table level is assumed to be
|
|
* formed from n pages.
|
|
*
|
|
* tbl: location of page table
|
|
* rtbl: address to be used for first level page table entry (typically tbl + PAGE_SIZE)
|
|
* vstart: virtual address of start of range
|
|
* vend: virtual address of end of range - we map [vstart, vend - 1]
|
|
* flags: flags to use to map last level entries
|
|
* phys: physical address corresponding to vstart - physical memory is contiguous
|
|
* pgds: the number of pgd entries
|
|
*
|
|
* Temporaries: istart, iend, tmp, count, sv - these need to be different registers
|
|
* Preserves: vstart, flags
|
|
* Corrupts: tbl, rtbl, vend, istart, iend, tmp, count, sv
|
|
*/
|
|
.macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
|
|
sub \vend, \vend, #1
|
|
add \rtbl, \tbl, #PAGE_SIZE
|
|
mov \sv, \rtbl
|
|
mov \count, #0
|
|
compute_indices \vstart, \vend, #PGDIR_SHIFT, \pgds, \istart, \iend, \count
|
|
populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
|
|
mov \tbl, \sv
|
|
mov \sv, \rtbl
|
|
|
|
#if SWAPPER_PGTABLE_LEVELS > 3
|
|
compute_indices \vstart, \vend, #PUD_SHIFT, #PTRS_PER_PUD, \istart, \iend, \count
|
|
populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
|
|
mov \tbl, \sv
|
|
mov \sv, \rtbl
|
|
#endif
|
|
|
|
#if SWAPPER_PGTABLE_LEVELS > 2
|
|
compute_indices \vstart, \vend, #SWAPPER_TABLE_SHIFT, #PTRS_PER_PMD, \istart, \iend, \count
|
|
populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
|
|
mov \tbl, \sv
|
|
#endif
|
|
|
|
compute_indices \vstart, \vend, #SWAPPER_BLOCK_SHIFT, #PTRS_PER_PTE, \istart, \iend, \count
|
|
bic \count, \phys, #SWAPPER_BLOCK_SIZE - 1
|
|
populate_entries \tbl, \count, \istart, \iend, \flags, #SWAPPER_BLOCK_SIZE, \tmp
|
|
.endm
|
|
|
|
/*
|
|
* Setup the initial page tables. We only setup the barest amount which is
|
|
* required to get the kernel running. The following sections are required:
|
|
* - identity mapping to enable the MMU (low address, TTBR0)
|
|
* - first few MB of the kernel linear mapping to jump to once the MMU has
|
|
* been enabled
|
|
*/
|
|
__create_page_tables:
|
|
mov x28, lr
|
|
|
|
/*
|
|
* Invalidate the idmap and swapper page tables to avoid potential
|
|
* dirty cache lines being evicted.
|
|
*/
|
|
adrp x0, idmap_pg_dir
|
|
adrp x1, swapper_pg_end
|
|
sub x1, x1, x0
|
|
bl __inval_dcache_area
|
|
|
|
/*
|
|
* Clear the idmap and swapper page tables.
|
|
*/
|
|
adrp x0, idmap_pg_dir
|
|
adrp x1, swapper_pg_end
|
|
sub x1, x1, x0
|
|
1: stp xzr, xzr, [x0], #16
|
|
stp xzr, xzr, [x0], #16
|
|
stp xzr, xzr, [x0], #16
|
|
stp xzr, xzr, [x0], #16
|
|
subs x1, x1, #64
|
|
b.ne 1b
|
|
|
|
mov x7, SWAPPER_MM_MMUFLAGS
|
|
|
|
/*
|
|
* Create the identity mapping.
|
|
*/
|
|
adrp x0, idmap_pg_dir
|
|
adrp x3, __idmap_text_start // __pa(__idmap_text_start)
|
|
|
|
/*
|
|
* VA_BITS may be too small to allow for an ID mapping to be created
|
|
* that covers system RAM if that is located sufficiently high in the
|
|
* physical address space. So for the ID map, use an extended virtual
|
|
* range in that case, and configure an additional translation level
|
|
* if needed.
|
|
*
|
|
* Calculate the maximum allowed value for TCR_EL1.T0SZ so that the
|
|
* entire ID map region can be mapped. As T0SZ == (64 - #bits used),
|
|
* this number conveniently equals the number of leading zeroes in
|
|
* the physical address of __idmap_text_end.
|
|
*/
|
|
adrp x5, __idmap_text_end
|
|
clz x5, x5
|
|
cmp x5, TCR_T0SZ(VA_BITS) // default T0SZ small enough?
|
|
b.ge 1f // .. then skip VA range extension
|
|
|
|
adr_l x6, idmap_t0sz
|
|
str x5, [x6]
|
|
dmb sy
|
|
dc ivac, x6 // Invalidate potentially stale cache line
|
|
|
|
#if (VA_BITS < 48)
|
|
#define EXTRA_SHIFT (PGDIR_SHIFT + PAGE_SHIFT - 3)
|
|
#define EXTRA_PTRS (1 << (PHYS_MASK_SHIFT - EXTRA_SHIFT))
|
|
|
|
/*
|
|
* If VA_BITS < 48, we have to configure an additional table level.
|
|
* First, we have to verify our assumption that the current value of
|
|
* VA_BITS was chosen such that all translation levels are fully
|
|
* utilised, and that lowering T0SZ will always result in an additional
|
|
* translation level to be configured.
|
|
*/
|
|
#if VA_BITS != EXTRA_SHIFT
|
|
#error "Mismatch between VA_BITS and page size/number of translation levels"
|
|
#endif
|
|
|
|
mov x4, EXTRA_PTRS
|
|
create_table_entry x0, x3, EXTRA_SHIFT, x4, x5, x6
|
|
#else
|
|
/*
|
|
* If VA_BITS == 48, we don't have to configure an additional
|
|
* translation level, but the top-level table has more entries.
|
|
*/
|
|
mov x4, #1 << (PHYS_MASK_SHIFT - PGDIR_SHIFT)
|
|
str_l x4, idmap_ptrs_per_pgd, x5
|
|
#endif
|
|
1:
|
|
ldr_l x4, idmap_ptrs_per_pgd
|
|
mov x5, x3 // __pa(__idmap_text_start)
|
|
adr_l x6, __idmap_text_end // __pa(__idmap_text_end)
|
|
|
|
map_memory x0, x1, x3, x6, x7, x3, x4, x10, x11, x12, x13, x14
|
|
|
|
/*
|
|
* Map the kernel image (starting with PHYS_OFFSET).
|
|
*/
|
|
adrp x0, swapper_pg_dir
|
|
mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text)
|
|
add x5, x5, x23 // add KASLR displacement
|
|
mov x4, PTRS_PER_PGD
|
|
adrp x6, _end // runtime __pa(_end)
|
|
adrp x3, _text // runtime __pa(_text)
|
|
sub x6, x6, x3 // _end - _text
|
|
add x6, x6, x5 // runtime __va(_end)
|
|
|
|
map_memory x0, x1, x5, x6, x7, x3, x4, x10, x11, x12, x13, x14
|
|
|
|
/*
|
|
* Since the page tables have been populated with non-cacheable
|
|
* accesses (MMU disabled), invalidate the idmap and swapper page
|
|
* tables again to remove any speculatively loaded cache lines.
|
|
*/
|
|
adrp x0, idmap_pg_dir
|
|
adrp x1, swapper_pg_end
|
|
sub x1, x1, x0
|
|
dmb sy
|
|
bl __inval_dcache_area
|
|
|
|
ret x28
|
|
ENDPROC(__create_page_tables)
|
|
.ltorg
|
|
|
|
/*
|
|
* The following fragment of code is executed with the MMU enabled.
|
|
*
|
|
* x0 = __PHYS_OFFSET
|
|
*/
|
|
__primary_switched:
|
|
adrp x4, init_thread_union
|
|
add sp, x4, #THREAD_SIZE
|
|
adr_l x5, init_task
|
|
msr sp_el0, x5 // Save thread_info
|
|
|
|
adr_l x8, vectors // load VBAR_EL1 with virtual
|
|
msr vbar_el1, x8 // vector table address
|
|
isb
|
|
|
|
stp xzr, x30, [sp, #-16]!
|
|
mov x29, sp
|
|
|
|
#ifdef CONFIG_SHADOW_CALL_STACK
|
|
adr_l x18, init_shadow_call_stack // Set shadow call stack
|
|
#endif
|
|
|
|
str_l x21, __fdt_pointer, x5 // Save FDT pointer
|
|
|
|
ldr_l x4, kimage_vaddr // Save the offset between
|
|
sub x4, x4, x0 // the kernel virtual and
|
|
str_l x4, kimage_voffset, x5 // physical mappings
|
|
|
|
// Clear BSS
|
|
adr_l x0, __bss_start
|
|
mov x1, xzr
|
|
adr_l x2, __bss_stop
|
|
sub x2, x2, x0
|
|
bl __pi_memset
|
|
dsb ishst // Make zero page visible to PTW
|
|
|
|
#ifdef CONFIG_KASAN
|
|
bl kasan_early_init
|
|
#endif
|
|
#ifdef CONFIG_RANDOMIZE_BASE
|
|
tst x23, ~(MIN_KIMG_ALIGN - 1) // already running randomized?
|
|
b.ne 0f
|
|
mov x0, x21 // pass FDT address in x0
|
|
bl kaslr_early_init // parse FDT for KASLR options
|
|
cbz x0, 0f // KASLR disabled? just proceed
|
|
orr x23, x23, x0 // record KASLR offset
|
|
ldp x29, x30, [sp], #16 // we must enable KASLR, return
|
|
ret // to __primary_switch()
|
|
0:
|
|
#endif
|
|
add sp, sp, #16
|
|
mov x29, #0
|
|
mov x30, #0
|
|
b start_kernel
|
|
ENDPROC(__primary_switched)
|
|
|
|
/*
|
|
* end early head section, begin head code that is also used for
|
|
* hotplug and needs to have the same protections as the text region
|
|
*/
|
|
.section ".idmap.text","awx"
|
|
|
|
ENTRY(kimage_vaddr)
|
|
.quad _text - TEXT_OFFSET
|
|
|
|
/*
|
|
* If we're fortunate enough to boot at EL2, ensure that the world is
|
|
* sane before dropping to EL1.
|
|
*
|
|
* Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in w0 if
|
|
* booted in EL1 or EL2 respectively.
|
|
*/
|
|
ENTRY(el2_setup)
|
|
msr SPsel, #1 // We want to use SP_EL{1,2}
|
|
mrs x0, CurrentEL
|
|
cmp x0, #CurrentEL_EL2
|
|
b.eq 1f
|
|
mov_q x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1)
|
|
msr sctlr_el1, x0
|
|
mov w0, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1
|
|
isb
|
|
ret
|
|
|
|
1: mov_q x0, (SCTLR_EL2_RES1 | ENDIAN_SET_EL2)
|
|
msr sctlr_el2, x0
|
|
|
|
#ifdef CONFIG_ARM64_VHE
|
|
/*
|
|
* Check for VHE being present. For the rest of the EL2 setup,
|
|
* x2 being non-zero indicates that we do have VHE, and that the
|
|
* kernel is intended to run at EL2.
|
|
*/
|
|
mrs x2, id_aa64mmfr1_el1
|
|
ubfx x2, x2, #8, #4
|
|
#else
|
|
mov x2, xzr
|
|
#endif
|
|
|
|
/* Hyp configuration. */
|
|
mov_q x0, HCR_HOST_NVHE_FLAGS
|
|
cbz x2, set_hcr
|
|
mov_q x0, HCR_HOST_VHE_FLAGS
|
|
set_hcr:
|
|
msr hcr_el2, x0
|
|
isb
|
|
|
|
/*
|
|
* Allow Non-secure EL1 and EL0 to access physical timer and counter.
|
|
* This is not necessary for VHE, since the host kernel runs in EL2,
|
|
* and EL0 accesses are configured in the later stage of boot process.
|
|
* Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout
|
|
* as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined
|
|
* to access CNTHCTL_EL2. This allows the kernel designed to run at EL1
|
|
* to transparently mess with the EL0 bits via CNTKCTL_EL1 access in
|
|
* EL2.
|
|
*/
|
|
cbnz x2, 1f
|
|
mrs x0, cnthctl_el2
|
|
orr x0, x0, #3 // Enable EL1 physical timers
|
|
msr cnthctl_el2, x0
|
|
1:
|
|
msr cntvoff_el2, xzr // Clear virtual offset
|
|
|
|
#ifdef CONFIG_ARM_GIC_V3
|
|
/* GICv3 system register access */
|
|
mrs x0, id_aa64pfr0_el1
|
|
ubfx x0, x0, #24, #4
|
|
cbz x0, 3f
|
|
|
|
mrs_s x0, SYS_ICC_SRE_EL2
|
|
orr x0, x0, #ICC_SRE_EL2_SRE // Set ICC_SRE_EL2.SRE==1
|
|
orr x0, x0, #ICC_SRE_EL2_ENABLE // Set ICC_SRE_EL2.Enable==1
|
|
msr_s SYS_ICC_SRE_EL2, x0
|
|
isb // Make sure SRE is now set
|
|
mrs_s x0, SYS_ICC_SRE_EL2 // Read SRE back,
|
|
tbz x0, #0, 3f // and check that it sticks
|
|
msr_s SYS_ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
|
|
|
|
3:
|
|
#endif
|
|
|
|
/* Populate ID registers. */
|
|
mrs x0, midr_el1
|
|
mrs x1, mpidr_el1
|
|
msr vpidr_el2, x0
|
|
msr vmpidr_el2, x1
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
msr hstr_el2, xzr // Disable CP15 traps to EL2
|
|
#endif
|
|
|
|
/* EL2 debug */
|
|
mrs x1, id_aa64dfr0_el1 // Check ID_AA64DFR0_EL1 PMUVer
|
|
sbfx x0, x1, #8, #4
|
|
cmp x0, #1
|
|
b.lt 4f // Skip if no PMU present
|
|
mrs x0, pmcr_el0 // Disable debug access traps
|
|
ubfx x0, x0, #11, #5 // to EL2 and allow access to
|
|
4:
|
|
csel x3, xzr, x0, lt // all PMU counters from EL1
|
|
|
|
/* Statistical profiling */
|
|
ubfx x0, x1, #32, #4 // Check ID_AA64DFR0_EL1 PMSVer
|
|
cbz x0, 7f // Skip if SPE not present
|
|
cbnz x2, 6f // VHE?
|
|
mrs_s x4, SYS_PMBIDR_EL1 // If SPE available at EL2,
|
|
and x4, x4, #(1 << SYS_PMBIDR_EL1_P_SHIFT)
|
|
cbnz x4, 5f // then permit sampling of physical
|
|
mov x4, #(1 << SYS_PMSCR_EL2_PCT_SHIFT | \
|
|
1 << SYS_PMSCR_EL2_PA_SHIFT)
|
|
msr_s SYS_PMSCR_EL2, x4 // addresses and physical counter
|
|
5:
|
|
mov x1, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)
|
|
orr x3, x3, x1 // If we don't have VHE, then
|
|
b 7f // use EL1&0 translation.
|
|
6: // For VHE, use EL2 translation
|
|
orr x3, x3, #MDCR_EL2_TPMS // and disable access from EL1
|
|
7:
|
|
msr mdcr_el2, x3 // Configure debug traps
|
|
|
|
/* LORegions */
|
|
mrs x1, id_aa64mmfr1_el1
|
|
ubfx x0, x1, #ID_AA64MMFR1_LOR_SHIFT, 4
|
|
cbz x0, 1f
|
|
msr_s SYS_LORC_EL1, xzr
|
|
1:
|
|
|
|
/* Stage-2 translation */
|
|
msr vttbr_el2, xzr
|
|
|
|
cbz x2, install_el2_stub
|
|
|
|
mov w0, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2
|
|
isb
|
|
ret
|
|
|
|
install_el2_stub:
|
|
/*
|
|
* When VHE is not in use, early init of EL2 and EL1 needs to be
|
|
* done here.
|
|
* When VHE _is_ in use, EL1 will not be used in the host and
|
|
* requires no configuration, and all non-hyp-specific EL2 setup
|
|
* will be done via the _EL1 system register aliases in __cpu_setup.
|
|
*/
|
|
mov_q x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1)
|
|
msr sctlr_el1, x0
|
|
|
|
/* Coprocessor traps. */
|
|
mov x0, #0x33ff
|
|
msr cptr_el2, x0 // Disable copro. traps to EL2
|
|
|
|
/* SVE register access */
|
|
mrs x1, id_aa64pfr0_el1
|
|
ubfx x1, x1, #ID_AA64PFR0_SVE_SHIFT, #4
|
|
cbz x1, 7f
|
|
|
|
bic x0, x0, #CPTR_EL2_TZ // Also disable SVE traps
|
|
msr cptr_el2, x0 // Disable copro. traps to EL2
|
|
isb
|
|
mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector
|
|
msr_s SYS_ZCR_EL2, x1 // length for EL1.
|
|
|
|
/* Hypervisor stub */
|
|
7: adr_l x0, __hyp_stub_vectors
|
|
msr vbar_el2, x0
|
|
|
|
/* spsr */
|
|
mov x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
|
|
PSR_MODE_EL1h)
|
|
msr spsr_el2, x0
|
|
msr elr_el2, lr
|
|
mov w0, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2
|
|
eret
|
|
ENDPROC(el2_setup)
|
|
|
|
/*
|
|
* Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
|
|
* in w0. See arch/arm64/include/asm/virt.h for more info.
|
|
*/
|
|
set_cpu_boot_mode_flag:
|
|
adr_l x1, __boot_cpu_mode
|
|
cmp w0, #BOOT_CPU_MODE_EL2
|
|
b.ne 1f
|
|
add x1, x1, #4
|
|
1: str w0, [x1] // This CPU has booted in EL1
|
|
dmb sy
|
|
dc ivac, x1 // Invalidate potentially stale cache line
|
|
ret
|
|
ENDPROC(set_cpu_boot_mode_flag)
|
|
|
|
/*
|
|
* These values are written with the MMU off, but read with the MMU on.
|
|
* Writers will invalidate the corresponding address, discarding up to a
|
|
* 'Cache Writeback Granule' (CWG) worth of data. The linker script ensures
|
|
* sufficient alignment that the CWG doesn't overlap another section.
|
|
*/
|
|
.pushsection ".mmuoff.data.write", "aw"
|
|
/*
|
|
* We need to find out the CPU boot mode long after boot, so we need to
|
|
* store it in a writable variable.
|
|
*
|
|
* This is not in .bss, because we set it sufficiently early that the boot-time
|
|
* zeroing of .bss would clobber it.
|
|
*/
|
|
ENTRY(__boot_cpu_mode)
|
|
.long BOOT_CPU_MODE_EL2
|
|
.long BOOT_CPU_MODE_EL1
|
|
/*
|
|
* The booting CPU updates the failed status @__early_cpu_boot_status,
|
|
* with MMU turned off.
|
|
*/
|
|
ENTRY(__early_cpu_boot_status)
|
|
.quad 0
|
|
|
|
.popsection
|
|
|
|
/*
|
|
* This provides a "holding pen" for platforms to hold all secondary
|
|
* cores are held until we're ready for them to initialise.
|
|
*/
|
|
ENTRY(secondary_holding_pen)
|
|
bl el2_setup // Drop to EL1, w0=cpu_boot_mode
|
|
bl set_cpu_boot_mode_flag
|
|
mrs x0, mpidr_el1
|
|
mov_q x1, MPIDR_HWID_BITMASK
|
|
and x0, x0, x1
|
|
adr_l x3, secondary_holding_pen_release
|
|
pen: ldr x4, [x3]
|
|
cmp x4, x0
|
|
b.eq secondary_startup
|
|
wfe
|
|
b pen
|
|
ENDPROC(secondary_holding_pen)
|
|
|
|
/*
|
|
* Secondary entry point that jumps straight into the kernel. Only to
|
|
* be used where CPUs are brought online dynamically by the kernel.
|
|
*/
|
|
ENTRY(secondary_entry)
|
|
bl el2_setup // Drop to EL1
|
|
bl set_cpu_boot_mode_flag
|
|
b secondary_startup
|
|
ENDPROC(secondary_entry)
|
|
|
|
secondary_startup:
|
|
/*
|
|
* Common entry point for secondary CPUs.
|
|
*/
|
|
bl __cpu_secondary_check52bitva
|
|
bl __cpu_setup // initialise processor
|
|
bl __enable_mmu
|
|
ldr x8, =__secondary_switched
|
|
br x8
|
|
ENDPROC(secondary_startup)
|
|
|
|
__secondary_switched:
|
|
adr_l x5, vectors
|
|
msr vbar_el1, x5
|
|
isb
|
|
|
|
adr_l x0, secondary_data
|
|
ldr x1, [x0, #CPU_BOOT_STACK] // get secondary_data.stack
|
|
mov sp, x1
|
|
ldr x2, [x0, #CPU_BOOT_TASK]
|
|
msr sp_el0, x2
|
|
#ifdef CONFIG_SHADOW_CALL_STACK
|
|
ldr x18, [x2, #TSK_TI_SCS] // set shadow call stack
|
|
str xzr, [x2, #TSK_TI_SCS] // limit visibility of saved SCS
|
|
#endif
|
|
mov x29, #0
|
|
mov x30, #0
|
|
b secondary_start_kernel
|
|
ENDPROC(__secondary_switched)
|
|
|
|
/*
|
|
* The booting CPU updates the failed status @__early_cpu_boot_status,
|
|
* with MMU turned off.
|
|
*
|
|
* update_early_cpu_boot_status tmp, status
|
|
* - Corrupts tmp1, tmp2
|
|
* - Writes 'status' to __early_cpu_boot_status and makes sure
|
|
* it is committed to memory.
|
|
*/
|
|
|
|
.macro update_early_cpu_boot_status status, tmp1, tmp2
|
|
mov \tmp2, #\status
|
|
adr_l \tmp1, __early_cpu_boot_status
|
|
str \tmp2, [\tmp1]
|
|
dmb sy
|
|
dc ivac, \tmp1 // Invalidate potentially stale cache line
|
|
.endm
|
|
|
|
/*
|
|
* Enable the MMU.
|
|
*
|
|
* x0 = SCTLR_EL1 value for turning on the MMU.
|
|
*
|
|
* Returns to the caller via x30/lr. This requires the caller to be covered
|
|
* by the .idmap.text section.
|
|
*
|
|
* Checks if the selected granule size is supported by the CPU.
|
|
* If it isn't, park the CPU
|
|
*/
|
|
ENTRY(__enable_mmu)
|
|
mrs x1, ID_AA64MMFR0_EL1
|
|
ubfx x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4
|
|
cmp x2, #ID_AA64MMFR0_TGRAN_SUPPORTED
|
|
b.ne __no_granule_support
|
|
update_early_cpu_boot_status 0, x1, x2
|
|
adrp x1, idmap_pg_dir
|
|
adrp x2, swapper_pg_dir
|
|
phys_to_ttbr x3, x1
|
|
phys_to_ttbr x4, x2
|
|
msr ttbr0_el1, x3 // load TTBR0
|
|
msr ttbr1_el1, x4 // load TTBR1
|
|
isb
|
|
msr sctlr_el1, x0
|
|
isb
|
|
/*
|
|
* Invalidate the local I-cache so that any instructions fetched
|
|
* speculatively from the PoC are discarded, since they may have
|
|
* been dynamically patched at the PoU.
|
|
*/
|
|
ic iallu
|
|
dsb nsh
|
|
isb
|
|
ret
|
|
ENDPROC(__enable_mmu)
|
|
|
|
ENTRY(__cpu_secondary_check52bitva)
|
|
#ifdef CONFIG_ARM64_52BIT_VA
|
|
ldr_l x0, vabits_user
|
|
cmp x0, #52
|
|
b.ne 2f
|
|
|
|
mrs_s x0, SYS_ID_AA64MMFR2_EL1
|
|
and x0, x0, #(0xf << ID_AA64MMFR2_LVA_SHIFT)
|
|
cbnz x0, 2f
|
|
|
|
adr_l x0, va52mismatch
|
|
mov w1, #1
|
|
strb w1, [x0]
|
|
dmb sy
|
|
dc ivac, x0 // Invalidate potentially stale cache line
|
|
|
|
update_early_cpu_boot_status CPU_STUCK_IN_KERNEL, x0, x1
|
|
1: wfe
|
|
wfi
|
|
b 1b
|
|
|
|
#endif
|
|
2: ret
|
|
ENDPROC(__cpu_secondary_check52bitva)
|
|
|
|
__no_granule_support:
|
|
/* Indicate that this CPU can't boot and is stuck in the kernel */
|
|
update_early_cpu_boot_status CPU_STUCK_IN_KERNEL, x1, x2
|
|
1:
|
|
wfe
|
|
wfi
|
|
b 1b
|
|
ENDPROC(__no_granule_support)
|
|
|
|
#ifdef CONFIG_RELOCATABLE
|
|
__relocate_kernel:
|
|
/*
|
|
* Iterate over each entry in the relocation table, and apply the
|
|
* relocations in place.
|
|
*/
|
|
ldr w9, =__rela_offset // offset to reloc table
|
|
ldr w10, =__rela_size // size of reloc table
|
|
|
|
mov_q x11, KIMAGE_VADDR // default virtual offset
|
|
add x11, x11, x23 // actual virtual offset
|
|
add x9, x9, x11 // __va(.rela)
|
|
add x10, x9, x10 // __va(.rela) + sizeof(.rela)
|
|
|
|
0: cmp x9, x10
|
|
b.hs 1f
|
|
ldp x12, x13, [x9], #24
|
|
ldr x14, [x9, #-8]
|
|
cmp w13, #R_AARCH64_RELATIVE
|
|
b.ne 0b
|
|
add x14, x14, x23 // relocate
|
|
str x14, [x12, x23]
|
|
b 0b
|
|
|
|
1:
|
|
#ifdef CONFIG_RELR
|
|
/*
|
|
* Apply RELR relocations.
|
|
*
|
|
* RELR is a compressed format for storing relative relocations. The
|
|
* encoded sequence of entries looks like:
|
|
* [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ]
|
|
*
|
|
* i.e. start with an address, followed by any number of bitmaps. The
|
|
* address entry encodes 1 relocation. The subsequent bitmap entries
|
|
* encode up to 63 relocations each, at subsequent offsets following
|
|
* the last address entry.
|
|
*
|
|
* The bitmap entries must have 1 in the least significant bit. The
|
|
* assumption here is that an address cannot have 1 in lsb. Odd
|
|
* addresses are not supported. Any odd addresses are stored in the RELA
|
|
* section, which is handled above.
|
|
*
|
|
* Excluding the least significant bit in the bitmap, each non-zero
|
|
* bit in the bitmap represents a relocation to be applied to
|
|
* a corresponding machine word that follows the base address
|
|
* word. The second least significant bit represents the machine
|
|
* word immediately following the initial address, and each bit
|
|
* that follows represents the next word, in linear order. As such,
|
|
* a single bitmap can encode up to 63 relocations in a 64-bit object.
|
|
*
|
|
* In this implementation we store the address of the next RELR table
|
|
* entry in x9, the address being relocated by the current address or
|
|
* bitmap entry in x13 and the address being relocated by the current
|
|
* bit in x14.
|
|
*
|
|
* Because addends are stored in place in the binary, RELR relocations
|
|
* cannot be applied idempotently. We use x24 to keep track of the
|
|
* currently applied displacement so that we can correctly relocate if
|
|
* __relocate_kernel is called twice with non-zero displacements (i.e.
|
|
* if there is both a physical misalignment and a KASLR displacement).
|
|
*/
|
|
ldr w9, =__relr_offset // offset to reloc table
|
|
ldr w10, =__relr_size // size of reloc table
|
|
add x9, x9, x11 // __va(.relr)
|
|
add x10, x9, x10 // __va(.relr) + sizeof(.relr)
|
|
|
|
sub x15, x23, x24 // delta from previous offset
|
|
cbz x15, 7f // nothing to do if unchanged
|
|
mov x24, x23 // save new offset
|
|
|
|
2: cmp x9, x10
|
|
b.hs 7f
|
|
ldr x11, [x9], #8
|
|
tbnz x11, #0, 3f // branch to handle bitmaps
|
|
add x13, x11, x23
|
|
ldr x12, [x13] // relocate address entry
|
|
add x12, x12, x15
|
|
str x12, [x13], #8 // adjust to start of bitmap
|
|
b 2b
|
|
|
|
3: mov x14, x13
|
|
4: lsr x11, x11, #1
|
|
cbz x11, 6f
|
|
tbz x11, #0, 5f // skip bit if not set
|
|
ldr x12, [x14] // relocate bit
|
|
add x12, x12, x15
|
|
str x12, [x14]
|
|
|
|
5: add x14, x14, #8 // move to next bit's address
|
|
b 4b
|
|
|
|
6: /*
|
|
* Move to the next bitmap's address. 8 is the word size, and 63 is the
|
|
* number of significant bits in a bitmap entry.
|
|
*/
|
|
add x13, x13, #(8 * 63)
|
|
b 2b
|
|
|
|
7:
|
|
#endif
|
|
ret
|
|
|
|
ENDPROC(__relocate_kernel)
|
|
#endif
|
|
|
|
__primary_switch:
|
|
#ifdef CONFIG_RANDOMIZE_BASE
|
|
mov x19, x0 // preserve new SCTLR_EL1 value
|
|
mrs x20, sctlr_el1 // preserve old SCTLR_EL1 value
|
|
#endif
|
|
|
|
bl __enable_mmu
|
|
#ifdef CONFIG_RELOCATABLE
|
|
#ifdef CONFIG_RELR
|
|
mov x24, #0 // no RELR displacement yet
|
|
#endif
|
|
bl __relocate_kernel
|
|
#ifdef CONFIG_RANDOMIZE_BASE
|
|
ldr x8, =__primary_switched
|
|
adrp x0, __PHYS_OFFSET
|
|
blr x8
|
|
|
|
/*
|
|
* If we return here, we have a KASLR displacement in x23 which we need
|
|
* to take into account by discarding the current kernel mapping and
|
|
* creating a new one.
|
|
*/
|
|
pre_disable_mmu_workaround
|
|
msr sctlr_el1, x20 // disable the MMU
|
|
isb
|
|
bl __create_page_tables // recreate kernel mapping
|
|
|
|
tlbi vmalle1 // Remove any stale TLB entries
|
|
dsb nsh
|
|
isb
|
|
|
|
msr sctlr_el1, x19 // re-enable the MMU
|
|
isb
|
|
ic iallu // flush instructions fetched
|
|
dsb nsh // via old mapping
|
|
isb
|
|
|
|
bl __relocate_kernel
|
|
#endif
|
|
#endif
|
|
ldr x8, =__primary_switched
|
|
adrp x0, __PHYS_OFFSET
|
|
br x8
|
|
ENDPROC(__primary_switch)
|