 021f653791
			
		
	
	
	021f653791
	
	
	
		
			
			The Generic Interrupt Controller (version 3) offers services that are similar to GICv2, with a number of additional features: - Affinity routing based on the CPU MPIDR (ARE) - System register for the CPU interfaces (SRE) - Support for more that 8 CPUs - Locality-specific Peripheral Interrupts (LPIs) - Interrupt Translation Services (ITS) This patch adds preliminary support for GICv3 with ARE and SRE, non-secure mode only. It relies on higher exception levels to grant ARE and SRE access. Support for LPI and ITS will be added at a later time. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Jason Cooper <jason@lakedaemon.net> Reviewed-by: Zi Shen Lim <zlim@broadcom.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Reviewed-by: Tirumalesh Chalamarla <tchalamarla@cavium.com> Reviewed-by: Yun Wu <wuyun.wu@huawei.com> Reviewed-by: Zhen Lei <thunder.leizhen@huawei.com> Tested-by: Tirumalesh Chalamarla<tchalamarla@cavium.com> Tested-by: Radha Mohan Chintakuntla <rchintakuntla@cavium.com> Acked-by: Radha Mohan Chintakuntla <rchintakuntla@cavium.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Reviewed-by: Mark Rutland <mark.rutland@arm.com> Link: https://lkml.kernel.org/r/1404140510-5382-3-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
		
			
				
	
	
		
			110 lines
		
	
	
	
		
			3.1 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
	
		
			3.1 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * Hypervisor stub
 | |
|  *
 | |
|  * Copyright (C) 2012 ARM Ltd.
 | |
|  * Author:	Marc Zyngier <marc.zyngier@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/init.h>
 | |
| #include <linux/linkage.h>
 | |
| #include <linux/irqchip/arm-gic-v3.h>
 | |
| 
 | |
| #include <asm/assembler.h>
 | |
| #include <asm/ptrace.h>
 | |
| #include <asm/virt.h>
 | |
| 
 | |
| 	.text
 | |
| 	.align 11
 | |
| 
 | |
| ENTRY(__hyp_stub_vectors)
 | |
| 	ventry	el2_sync_invalid		// Synchronous EL2t
 | |
| 	ventry	el2_irq_invalid			// IRQ EL2t
 | |
| 	ventry	el2_fiq_invalid			// FIQ EL2t
 | |
| 	ventry	el2_error_invalid		// Error EL2t
 | |
| 
 | |
| 	ventry	el2_sync_invalid		// Synchronous EL2h
 | |
| 	ventry	el2_irq_invalid			// IRQ EL2h
 | |
| 	ventry	el2_fiq_invalid			// FIQ EL2h
 | |
| 	ventry	el2_error_invalid		// Error EL2h
 | |
| 
 | |
| 	ventry	el1_sync			// Synchronous 64-bit EL1
 | |
| 	ventry	el1_irq_invalid			// IRQ 64-bit EL1
 | |
| 	ventry	el1_fiq_invalid			// FIQ 64-bit EL1
 | |
| 	ventry	el1_error_invalid		// Error 64-bit EL1
 | |
| 
 | |
| 	ventry	el1_sync_invalid		// Synchronous 32-bit EL1
 | |
| 	ventry	el1_irq_invalid			// IRQ 32-bit EL1
 | |
| 	ventry	el1_fiq_invalid			// FIQ 32-bit EL1
 | |
| 	ventry	el1_error_invalid		// Error 32-bit EL1
 | |
| ENDPROC(__hyp_stub_vectors)
 | |
| 
 | |
| 	.align 11
 | |
| 
 | |
| el1_sync:
 | |
| 	mrs	x1, esr_el2
 | |
| 	lsr	x1, x1, #26
 | |
| 	cmp	x1, #0x16
 | |
| 	b.ne	2f				// Not an HVC trap
 | |
| 	cbz	x0, 1f
 | |
| 	msr	vbar_el2, x0			// Set vbar_el2
 | |
| 	b	2f
 | |
| 1:	mrs	x0, vbar_el2			// Return vbar_el2
 | |
| 2:	eret
 | |
| ENDPROC(el1_sync)
 | |
| 
 | |
| .macro invalid_vector	label
 | |
| \label:
 | |
| 	b \label
 | |
| ENDPROC(\label)
 | |
| .endm
 | |
| 
 | |
| 	invalid_vector	el2_sync_invalid
 | |
| 	invalid_vector	el2_irq_invalid
 | |
| 	invalid_vector	el2_fiq_invalid
 | |
| 	invalid_vector	el2_error_invalid
 | |
| 	invalid_vector	el1_sync_invalid
 | |
| 	invalid_vector	el1_irq_invalid
 | |
| 	invalid_vector	el1_fiq_invalid
 | |
| 	invalid_vector	el1_error_invalid
 | |
| 
 | |
| /*
 | |
|  * __hyp_set_vectors: Call this after boot to set the initial hypervisor
 | |
|  * vectors as part of hypervisor installation.  On an SMP system, this should
 | |
|  * be called on each CPU.
 | |
|  *
 | |
|  * x0 must be the physical address of the new vector table, and must be
 | |
|  * 2KB aligned.
 | |
|  *
 | |
|  * Before calling this, you must check that the stub hypervisor is installed
 | |
|  * everywhere, by waiting for any secondary CPUs to be brought up and then
 | |
|  * checking that is_hyp_mode_available() is true.
 | |
|  *
 | |
|  * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or
 | |
|  * something else went wrong... in such cases, trying to install a new
 | |
|  * hypervisor is unlikely to work as desired.
 | |
|  *
 | |
|  * When you call into your shiny new hypervisor, sp_el2 will contain junk,
 | |
|  * so you will need to set that to something sensible at the new hypervisor's
 | |
|  * initialisation entry point.
 | |
|  */
 | |
| 
 | |
| ENTRY(__hyp_get_vectors)
 | |
| 	mov	x0, xzr
 | |
| 	// fall through
 | |
| ENTRY(__hyp_set_vectors)
 | |
| 	hvc	#0
 | |
| 	ret
 | |
| ENDPROC(__hyp_get_vectors)
 | |
| ENDPROC(__hyp_set_vectors)
 |