You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Pull pvops into release branch
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
Paravirt_ops on IA64
|
||||
====================
|
||||
21 May 2008, Isaku Yamahata <yamahata@valinux.co.jp>
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
The aim of this documentation is to help with maintainability and/or to
|
||||
encourage people to use paravirt_ops/IA64.
|
||||
|
||||
paravirt_ops (pv_ops in short) is a way for virtualization support of
|
||||
Linux kernel on x86. Several ways for virtualization support were
|
||||
proposed, paravirt_ops is the winner.
|
||||
On the other hand, now there are also several IA64 virtualization
|
||||
technologies like kvm/IA64, xen/IA64 and many other academic IA64
|
||||
hypervisors so that it is good to add generic virtualization
|
||||
infrastructure on Linux/IA64.
|
||||
|
||||
|
||||
What is paravirt_ops?
|
||||
---------------------
|
||||
It has been developed on x86 as virtualization support via API, not ABI.
|
||||
It allows each hypervisor to override operations which are important for
|
||||
hypervisors at API level. And it allows a single kernel binary to run on
|
||||
all supported execution environments including native machine.
|
||||
Essentially paravirt_ops is a set of function pointers which represent
|
||||
operations corresponding to low level sensitive instructions and high
|
||||
level functionalities in various area. But one significant difference
|
||||
from usual function pointer table is that it allows optimization with
|
||||
binary patch. It is because some of these operations are very
|
||||
performance sensitive and indirect call overhead is not negligible.
|
||||
With binary patch, indirect C function call can be transformed into
|
||||
direct C function call or in-place execution to eliminate the overhead.
|
||||
|
||||
Thus, operations of paravirt_ops are classified into three categories.
|
||||
- simple indirect call
|
||||
These operations correspond to high level functionality so that the
|
||||
overhead of indirect call isn't very important.
|
||||
|
||||
- indirect call which allows optimization with binary patch
|
||||
Usually these operations correspond to low level instructions. They
|
||||
are called frequently and performance critical. So the overhead is
|
||||
very important.
|
||||
|
||||
- a set of macros for hand written assembly code
|
||||
Hand written assembly codes (.S files) also need paravirtualization
|
||||
because they include sensitive instructions or some of code paths in
|
||||
them are very performance critical.
|
||||
|
||||
|
||||
The relation to the IA64 machine vector
|
||||
---------------------------------------
|
||||
Linux/IA64 has the IA64 machine vector functionality which allows the
|
||||
kernel to switch implementations (e.g. initialization, ipi, dma api...)
|
||||
depending on executing platform.
|
||||
We can replace some implementations very easily defining a new machine
|
||||
vector. Thus another approach for virtualization support would be
|
||||
enhancing the machine vector functionality.
|
||||
But paravirt_ops approach was taken because
|
||||
- virtualization support needs wider support than machine vector does.
|
||||
e.g. low level instruction paravirtualization. It must be
|
||||
initialized very early before platform detection.
|
||||
|
||||
- virtualization support needs more functionality like binary patch.
|
||||
Probably the calling overhead might not be very large compared to the
|
||||
emulation overhead of virtualization. However in the native case, the
|
||||
overhead should be eliminated completely.
|
||||
A single kernel binary should run on each environment including native,
|
||||
and the overhead of paravirt_ops on native environment should be as
|
||||
small as possible.
|
||||
|
||||
- for full virtualization technology, e.g. KVM/IA64 or
|
||||
Xen/IA64 HVM domain, the result would be
|
||||
(the emulated platform machine vector. probably dig) + (pv_ops).
|
||||
This means that the virtualization support layer should be under
|
||||
the machine vector layer.
|
||||
|
||||
Possibly it might be better to move some function pointers from
|
||||
paravirt_ops to machine vector. In fact, Xen domU case utilizes both
|
||||
pv_ops and machine vector.
|
||||
|
||||
|
||||
IA64 paravirt_ops
|
||||
-----------------
|
||||
In this section, the concrete paravirt_ops will be discussed.
|
||||
Because of the architecture difference between ia64 and x86, the
|
||||
resulting set of functions is very different from x86 pv_ops.
|
||||
|
||||
- C function pointer tables
|
||||
They are not very performance critical so that simple C indirect
|
||||
function call is acceptable. The following structures are defined at
|
||||
this moment. For details see linux/include/asm-ia64/paravirt.h
|
||||
- struct pv_info
|
||||
This structure describes the execution environment.
|
||||
- struct pv_init_ops
|
||||
This structure describes the various initialization hooks.
|
||||
- struct pv_iosapic_ops
|
||||
This structure describes hooks to iosapic operations.
|
||||
- struct pv_irq_ops
|
||||
This structure describes hooks to irq related operations
|
||||
- struct pv_time_op
|
||||
This structure describes hooks to steal time accounting.
|
||||
|
||||
- a set of indirect calls which need optimization
|
||||
Currently this class of functions correspond to a subset of IA64
|
||||
intrinsics. At this moment the optimization with binary patch isn't
|
||||
implemented yet.
|
||||
struct pv_cpu_op is defined. For details see
|
||||
linux/include/asm-ia64/paravirt_privop.h
|
||||
Mostly they correspond to ia64 intrinsics 1-to-1.
|
||||
Caveat: Now they are defined as C indirect function pointers, but in
|
||||
order to support binary patch optimization, they will be changed
|
||||
using GCC extended inline assembly code.
|
||||
|
||||
- a set of macros for hand written assembly code (.S files)
|
||||
For maintenance purpose, the taken approach for .S files is single
|
||||
source code and compile multiple times with different macros definitions.
|
||||
Each pv_ops instance must define those macros to compile.
|
||||
The important thing here is that sensitive, but non-privileged
|
||||
instructions must be paravirtualized and that some privileged
|
||||
instructions also need paravirtualization for reasonable performance.
|
||||
Developers who modify .S files must be aware of that. At this moment
|
||||
an easy checker is implemented to detect paravirtualization breakage.
|
||||
But it doesn't cover all the cases.
|
||||
|
||||
Sometimes this set of macros is called pv_cpu_asm_op. But there is no
|
||||
corresponding structure in the source code.
|
||||
Those macros mostly 1:1 correspond to a subset of privileged
|
||||
instructions. See linux/include/asm-ia64/native/inst.h.
|
||||
And some functions written in assembly also need to be overrided so
|
||||
that each pv_ops instance have to define some macros. Again see
|
||||
linux/include/asm-ia64/native/inst.h.
|
||||
|
||||
|
||||
Those structures must be initialized very early before start_kernel.
|
||||
Probably initialized in head.S using multi entry point or some other trick.
|
||||
For native case implementation see linux/arch/ia64/kernel/paravirt.c.
|
||||
@@ -100,3 +100,9 @@ define archhelp
|
||||
echo ' boot - Build vmlinux and bootloader for Ski simulator'
|
||||
echo '* unwcheck - Check vmlinux for invalid unwind info'
|
||||
endef
|
||||
|
||||
archprepare: make_nr_irqs_h FORCE
|
||||
PHONY += make_nr_irqs_h FORCE
|
||||
|
||||
make_nr_irqs_h: FORCE
|
||||
$(Q)$(MAKE) $(build)=arch/ia64/kernel include/asm-ia64/nr-irqs.h
|
||||
|
||||
@@ -36,6 +36,8 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o
|
||||
mca_recovery-y += mca_drv.o mca_drv_asm.o
|
||||
obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
|
||||
|
||||
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o
|
||||
|
||||
obj-$(CONFIG_IA64_ESI) += esi.o
|
||||
ifneq ($(CONFIG_IA64_ESI),)
|
||||
obj-y += esi_stub.o # must be in kernel proper
|
||||
@@ -70,3 +72,45 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
|
||||
# We must build gate.so before we can assemble it.
|
||||
# Note: kbuild does not track this dependency due to usage of .incbin
|
||||
$(obj)/gate-data.o: $(obj)/gate.so
|
||||
|
||||
# Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config
|
||||
define sed-y
|
||||
"/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
|
||||
endef
|
||||
quiet_cmd_nr_irqs = GEN $@
|
||||
define cmd_nr_irqs
|
||||
(set -e; \
|
||||
echo "#ifndef __ASM_NR_IRQS_H__"; \
|
||||
echo "#define __ASM_NR_IRQS_H__"; \
|
||||
echo "/*"; \
|
||||
echo " * DO NOT MODIFY."; \
|
||||
echo " *"; \
|
||||
echo " * This file was generated by Kbuild"; \
|
||||
echo " *"; \
|
||||
echo " */"; \
|
||||
echo ""; \
|
||||
sed -ne $(sed-y) $<; \
|
||||
echo ""; \
|
||||
echo "#endif" ) > $@
|
||||
endef
|
||||
|
||||
# We use internal kbuild rules to avoid the "is up to date" message from make
|
||||
arch/$(SRCARCH)/kernel/nr-irqs.s: $(srctree)/arch/$(SRCARCH)/kernel/nr-irqs.c \
|
||||
$(wildcard $(srctree)/include/asm-ia64/*/irq.h)
|
||||
$(Q)mkdir -p $(dir $@)
|
||||
$(call if_changed_dep,cc_s_c)
|
||||
|
||||
include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
|
||||
$(Q)mkdir -p $(dir $@)
|
||||
$(call cmd,nr_irqs)
|
||||
|
||||
clean-files += $(objtree)/include/asm-ia64/nr-irqs.h
|
||||
|
||||
#
|
||||
# native ivt.S and entry.S
|
||||
#
|
||||
ASM_PARAVIRT_OBJS = ivt.o entry.o
|
||||
define paravirtualized_native
|
||||
AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE
|
||||
endef
|
||||
$(foreach obj,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_native,$(obj))))
|
||||
|
||||
+72
-43
@@ -22,6 +22,11 @@
|
||||
* Patrick O'Rourke <orourke@missioncriticallinux.com>
|
||||
* 11/07/2000
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
|
||||
* VA Linux Systems Japan K.K.
|
||||
* pv_ops.
|
||||
*/
|
||||
/*
|
||||
* Global (preserved) predicate usage on syscall entry/exit path:
|
||||
*
|
||||
@@ -45,6 +50,7 @@
|
||||
|
||||
#include "minstate.h"
|
||||
|
||||
#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
|
||||
/*
|
||||
* execve() is special because in case of success, we need to
|
||||
* setup a null register window frame.
|
||||
@@ -173,6 +179,7 @@ GLOBAL_ENTRY(sys_clone)
|
||||
mov rp=loc0
|
||||
br.ret.sptk.many rp
|
||||
END(sys_clone)
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
||||
/*
|
||||
* prev_task <- ia64_switch_to(struct task_struct *next)
|
||||
@@ -180,7 +187,7 @@ END(sys_clone)
|
||||
* called. The code starting at .map relies on this. The rest of the code
|
||||
* doesn't care about the interrupt masking status.
|
||||
*/
|
||||
GLOBAL_ENTRY(ia64_switch_to)
|
||||
GLOBAL_ENTRY(__paravirt_switch_to)
|
||||
.prologue
|
||||
alloc r16=ar.pfs,1,0,0,0
|
||||
DO_SAVE_SWITCH_STACK
|
||||
@@ -204,7 +211,7 @@ GLOBAL_ENTRY(ia64_switch_to)
|
||||
;;
|
||||
.done:
|
||||
ld8 sp=[r21] // load kernel stack pointer of new task
|
||||
mov IA64_KR(CURRENT)=in0 // update "current" application register
|
||||
MOV_TO_KR(CURRENT, in0, r8, r9) // update "current" application register
|
||||
mov r8=r13 // return pointer to previously running task
|
||||
mov r13=in0 // set "current" pointer
|
||||
;;
|
||||
@@ -216,26 +223,25 @@ GLOBAL_ENTRY(ia64_switch_to)
|
||||
br.ret.sptk.many rp // boogie on out in new context
|
||||
|
||||
.map:
|
||||
rsm psr.ic // interrupts (psr.i) are already disabled here
|
||||
RSM_PSR_IC(r25) // interrupts (psr.i) are already disabled here
|
||||
movl r25=PAGE_KERNEL
|
||||
;;
|
||||
srlz.d
|
||||
or r23=r25,r20 // construct PA | page properties
|
||||
mov r25=IA64_GRANULE_SHIFT<<2
|
||||
;;
|
||||
mov cr.itir=r25
|
||||
mov cr.ifa=in0 // VA of next task...
|
||||
MOV_TO_ITIR(p0, r25, r8)
|
||||
MOV_TO_IFA(in0, r8) // VA of next task...
|
||||
;;
|
||||
mov r25=IA64_TR_CURRENT_STACK
|
||||
mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped...
|
||||
MOV_TO_KR(CURRENT_STACK, r26, r8, r9) // remember last page we mapped...
|
||||
;;
|
||||
itr.d dtr[r25]=r23 // wire in new mapping...
|
||||
ssm psr.ic // reenable the psr.ic bit
|
||||
;;
|
||||
srlz.d
|
||||
SSM_PSR_IC_AND_SRLZ_D(r8, r9) // reenable the psr.ic bit
|
||||
br.cond.sptk .done
|
||||
END(ia64_switch_to)
|
||||
END(__paravirt_switch_to)
|
||||
|
||||
#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
|
||||
/*
|
||||
* Note that interrupts are enabled during save_switch_stack and load_switch_stack. This
|
||||
* means that we may get an interrupt with "sp" pointing to the new kernel stack while
|
||||
@@ -375,7 +381,7 @@ END(save_switch_stack)
|
||||
* - b7 holds address to return to
|
||||
* - must not touch r8-r11
|
||||
*/
|
||||
ENTRY(load_switch_stack)
|
||||
GLOBAL_ENTRY(load_switch_stack)
|
||||
.prologue
|
||||
.altrp b7
|
||||
|
||||
@@ -571,7 +577,7 @@ GLOBAL_ENTRY(ia64_trace_syscall)
|
||||
.ret3:
|
||||
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
|
||||
(pUStk) rsm psr.i // disable interrupts
|
||||
br.cond.sptk .work_pending_syscall_end
|
||||
br.cond.sptk ia64_work_pending_syscall_end
|
||||
|
||||
strace_error:
|
||||
ld8 r3=[r2] // load pt_regs.r8
|
||||
@@ -636,8 +642,17 @@ GLOBAL_ENTRY(ia64_ret_from_syscall)
|
||||
adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
|
||||
mov r10=r0 // clear error indication in r10
|
||||
(p7) br.cond.spnt handle_syscall_error // handle potential syscall failure
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
;;
|
||||
br.cond.sptk.few ia64_leave_syscall
|
||||
;;
|
||||
#endif /* CONFIG_PARAVIRT */
|
||||
END(ia64_ret_from_syscall)
|
||||
#ifndef CONFIG_PARAVIRT
|
||||
// fall through
|
||||
#endif
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
||||
/*
|
||||
* ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
|
||||
* need to switch to bank 0 and doesn't restore the scratch registers.
|
||||
@@ -682,7 +697,7 @@ END(ia64_ret_from_syscall)
|
||||
* ar.csd: cleared
|
||||
* ar.ssd: cleared
|
||||
*/
|
||||
ENTRY(ia64_leave_syscall)
|
||||
GLOBAL_ENTRY(__paravirt_leave_syscall)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
/*
|
||||
* work.need_resched etc. mustn't get changed by this CPU before it returns to
|
||||
@@ -692,11 +707,11 @@ ENTRY(ia64_leave_syscall)
|
||||
* extra work. We always check for extra work when returning to user-level.
|
||||
* With CONFIG_PREEMPT, we also check for extra work when the preempt_count
|
||||
* is 0. After extra work processing has been completed, execution
|
||||
* resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
|
||||
* resumes at ia64_work_processed_syscall with p6 set to 1 if the extra-work-check
|
||||
* needs to be redone.
|
||||
*/
|
||||
#ifdef CONFIG_PREEMPT
|
||||
rsm psr.i // disable interrupts
|
||||
RSM_PSR_I(p0, r2, r18) // disable interrupts
|
||||
cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
|
||||
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
|
||||
;;
|
||||
@@ -706,11 +721,12 @@ ENTRY(ia64_leave_syscall)
|
||||
;;
|
||||
cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
|
||||
#else /* !CONFIG_PREEMPT */
|
||||
(pUStk) rsm psr.i
|
||||
RSM_PSR_I(pUStk, r2, r18)
|
||||
cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
|
||||
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
|
||||
#endif
|
||||
.work_processed_syscall:
|
||||
.global __paravirt_work_processed_syscall;
|
||||
__paravirt_work_processed_syscall:
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
adds r2=PT(LOADRS)+16,r12
|
||||
(pUStk) mov.m r22=ar.itc // fetch time at leave
|
||||
@@ -744,7 +760,7 @@ ENTRY(ia64_leave_syscall)
|
||||
(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE!
|
||||
;;
|
||||
invala // M0|1 invalidate ALAT
|
||||
rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection
|
||||
RSM_PSR_I_IC(r28, r29, r30) // M2 turn off interrupts and interruption collection
|
||||
cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs
|
||||
|
||||
ld8 r29=[r2],16 // M0|1 load cr.ipsr
|
||||
@@ -765,7 +781,7 @@ ENTRY(ia64_leave_syscall)
|
||||
;;
|
||||
#endif
|
||||
ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
|
||||
(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
|
||||
MOV_FROM_PSR(pKStk, r22, r21) // M2 read PSR now that interrupts are disabled
|
||||
nop 0
|
||||
;;
|
||||
ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
|
||||
@@ -798,7 +814,7 @@ ENTRY(ia64_leave_syscall)
|
||||
|
||||
srlz.d // M0 ensure interruption collection is off (for cover)
|
||||
shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
|
||||
cover // B add current frame into dirty partition & set cr.ifs
|
||||
COVER // B add current frame into dirty partition & set cr.ifs
|
||||
;;
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
mov r19=ar.bsp // M2 get new backing store pointer
|
||||
@@ -823,8 +839,9 @@ ENTRY(ia64_leave_syscall)
|
||||
mov.m ar.ssd=r0 // M2 clear ar.ssd
|
||||
mov f11=f0 // F clear f11
|
||||
br.cond.sptk.many rbs_switch // B
|
||||
END(ia64_leave_syscall)
|
||||
END(__paravirt_leave_syscall)
|
||||
|
||||
#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
@@ -835,10 +852,20 @@ GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
|
||||
st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
|
||||
.mem.offset 8,0
|
||||
st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
;;
|
||||
// don't fall through, ia64_leave_kernel may be #define'd
|
||||
br.cond.sptk.few ia64_leave_kernel
|
||||
;;
|
||||
#endif /* CONFIG_PARAVIRT */
|
||||
END(ia64_ret_from_ia32_execve)
|
||||
#ifndef CONFIG_PARAVIRT
|
||||
// fall through
|
||||
#endif
|
||||
#endif /* CONFIG_IA32_SUPPORT */
|
||||
GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
||||
GLOBAL_ENTRY(__paravirt_leave_kernel)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
/*
|
||||
* work.need_resched etc. mustn't get changed by this CPU before it returns to
|
||||
@@ -852,7 +879,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
* needs to be redone.
|
||||
*/
|
||||
#ifdef CONFIG_PREEMPT
|
||||
rsm psr.i // disable interrupts
|
||||
RSM_PSR_I(p0, r17, r31) // disable interrupts
|
||||
cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
|
||||
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
|
||||
;;
|
||||
@@ -862,7 +889,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
;;
|
||||
cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
|
||||
#else
|
||||
(pUStk) rsm psr.i
|
||||
RSM_PSR_I(pUStk, r17, r31)
|
||||
cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
|
||||
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
|
||||
#endif
|
||||
@@ -910,7 +937,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
mov ar.csd=r30
|
||||
mov ar.ssd=r31
|
||||
;;
|
||||
rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection
|
||||
RSM_PSR_I_IC(r23, r22, r25) // initiate turning off of interrupt and interruption collection
|
||||
invala // invalidate ALAT
|
||||
;;
|
||||
ld8.fill r22=[r2],24
|
||||
@@ -942,7 +969,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
mov ar.ccv=r15
|
||||
;;
|
||||
ldf.fill f11=[r2]
|
||||
bsw.0 // switch back to bank 0 (no stop bit required beforehand...)
|
||||
BSW_0(r2, r3, r15) // switch back to bank 0 (no stop bit required beforehand...)
|
||||
;;
|
||||
(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
|
||||
adds r16=PT(CR_IPSR)+16,r12
|
||||
@@ -950,12 +977,12 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
.pred.rel.mutex pUStk,pKStk
|
||||
(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
|
||||
MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled
|
||||
(pUStk) mov.m r22=ar.itc // M fetch time at leave
|
||||
nop.i 0
|
||||
;;
|
||||
#else
|
||||
(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
|
||||
MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled
|
||||
nop.i 0
|
||||
nop.i 0
|
||||
;;
|
||||
@@ -1027,7 +1054,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
* NOTE: alloc, loadrs, and cover can't be predicated.
|
||||
*/
|
||||
(pNonSys) br.cond.dpnt dont_preserve_current_frame
|
||||
cover // add current frame into dirty partition and set cr.ifs
|
||||
COVER // add current frame into dirty partition and set cr.ifs
|
||||
;;
|
||||
mov r19=ar.bsp // get new backing store pointer
|
||||
rbs_switch:
|
||||
@@ -1130,16 +1157,16 @@ skip_rbs_switch:
|
||||
(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp
|
||||
(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise
|
||||
;;
|
||||
mov cr.ipsr=r29 // M2
|
||||
MOV_TO_IPSR(p0, r29, r25) // M2
|
||||
mov ar.pfs=r26 // I0
|
||||
(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise
|
||||
|
||||
(p9) mov cr.ifs=r30 // M2
|
||||
MOV_TO_IFS(p9, r30, r25)// M2
|
||||
mov b0=r21 // I0
|
||||
(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise
|
||||
|
||||
mov ar.fpsr=r20 // M2
|
||||
mov cr.iip=r28 // M2
|
||||
MOV_TO_IIP(r28, r25) // M2
|
||||
nop 0
|
||||
;;
|
||||
(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode
|
||||
@@ -1148,7 +1175,7 @@ skip_rbs_switch:
|
||||
|
||||
mov ar.rsc=r27 // M2
|
||||
mov pr=r31,-1 // I0
|
||||
rfi // B
|
||||
RFI // B
|
||||
|
||||
/*
|
||||
* On entry:
|
||||
@@ -1174,35 +1201,36 @@ skip_rbs_switch:
|
||||
;;
|
||||
(pKStk) st4 [r20]=r21
|
||||
#endif
|
||||
ssm psr.i // enable interrupts
|
||||
SSM_PSR_I(p0, p6, r2) // enable interrupts
|
||||
br.call.spnt.many rp=schedule
|
||||
.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 (re-check)
|
||||
rsm psr.i // disable interrupts
|
||||
RSM_PSR_I(p0, r2, r20) // disable interrupts
|
||||
;;
|
||||
#ifdef CONFIG_PREEMPT
|
||||
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
|
||||
;;
|
||||
(pKStk) st4 [r20]=r0 // preempt_count() <- 0
|
||||
#endif
|
||||
(pLvSys)br.cond.sptk.few .work_pending_syscall_end
|
||||
(pLvSys)br.cond.sptk.few __paravirt_pending_syscall_end
|
||||
br.cond.sptk.many .work_processed_kernel
|
||||
|
||||
.notify:
|
||||
(pUStk) br.call.spnt.many rp=notify_resume_user
|
||||
.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 (don't re-check)
|
||||
(pLvSys)br.cond.sptk.few .work_pending_syscall_end
|
||||
(pLvSys)br.cond.sptk.few __paravirt_pending_syscall_end
|
||||
br.cond.sptk.many .work_processed_kernel
|
||||
|
||||
.work_pending_syscall_end:
|
||||
.global __paravirt_pending_syscall_end;
|
||||
__paravirt_pending_syscall_end:
|
||||
adds r2=PT(R8)+16,r12
|
||||
adds r3=PT(R10)+16,r12
|
||||
;;
|
||||
ld8 r8=[r2]
|
||||
ld8 r10=[r3]
|
||||
br.cond.sptk.many .work_processed_syscall
|
||||
|
||||
END(ia64_leave_kernel)
|
||||
br.cond.sptk.many __paravirt_work_processed_syscall_target
|
||||
END(__paravirt_leave_kernel)
|
||||
|
||||
#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
|
||||
ENTRY(handle_syscall_error)
|
||||
/*
|
||||
* Some system calls (e.g., ptrace, mmap) can return arbitrary values which could
|
||||
@@ -1244,7 +1272,7 @@ END(ia64_invoke_schedule_tail)
|
||||
* We declare 8 input registers so the system call args get preserved,
|
||||
* in case we need to restart a system call.
|
||||
*/
|
||||
ENTRY(notify_resume_user)
|
||||
GLOBAL_ENTRY(notify_resume_user)
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
|
||||
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
|
||||
mov r9=ar.unat
|
||||
@@ -1306,7 +1334,7 @@ ENTRY(sys_rt_sigreturn)
|
||||
adds sp=16,sp
|
||||
;;
|
||||
ld8 r9=[sp] // load new ar.unat
|
||||
mov.sptk b7=r8,ia64_leave_kernel
|
||||
mov.sptk b7=r8,ia64_native_leave_kernel
|
||||
;;
|
||||
mov ar.unat=r9
|
||||
br.many b7
|
||||
@@ -1665,3 +1693,4 @@ sys_call_table:
|
||||
data8 sys_timerfd_gettime
|
||||
|
||||
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
||||
@@ -26,11 +26,14 @@
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/pal.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/mca_asm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
#define SAL_PSR_BITS_TO_SET \
|
||||
@@ -367,6 +370,44 @@ start_ap:
|
||||
;;
|
||||
(isBP) st8 [r2]=r28 // save the address of the boot param area passed by the bootloader
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
|
||||
movl r14=hypervisor_setup_hooks
|
||||
movl r15=hypervisor_type
|
||||
mov r16=num_hypervisor_hooks
|
||||
;;
|
||||
ld8 r2=[r15]
|
||||
;;
|
||||
cmp.ltu p7,p0=r2,r16 // array size check
|
||||
shladd r8=r2,3,r14
|
||||
;;
|
||||
(p7) ld8 r9=[r8]
|
||||
;;
|
||||
(p7) mov b1=r9
|
||||
(p7) cmp.ne.unc p7,p0=r9,r0 // no actual branch to NULL
|
||||
;;
|
||||
(p7) br.call.sptk.many rp=b1
|
||||
|
||||
__INITDATA
|
||||
|
||||
default_setup_hook = 0 // Currently nothing needs to be done.
|
||||
|
||||
.weak xen_setup_hook
|
||||
|
||||
.global hypervisor_type
|
||||
hypervisor_type:
|
||||
data8 PARAVIRT_HYPERVISOR_TYPE_DEFAULT
|
||||
|
||||
// must have the same order with PARAVIRT_HYPERVISOR_TYPE_xxx
|
||||
|
||||
hypervisor_setup_hooks:
|
||||
data8 default_setup_hook
|
||||
data8 xen_setup_hook
|
||||
num_hypervisor_hooks = (. - hypervisor_setup_hooks) / 8
|
||||
.previous
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
(isAP) br.call.sptk.many rp=start_secondary
|
||||
.ret0:
|
||||
|
||||
+29
-16
@@ -585,6 +585,15 @@ static inline int irq_is_shared (int irq)
|
||||
return (iosapic_intr_info[irq].count > 1);
|
||||
}
|
||||
|
||||
struct irq_chip*
|
||||
ia64_native_iosapic_get_irq_chip(unsigned long trigger)
|
||||
{
|
||||
if (trigger == IOSAPIC_EDGE)
|
||||
return &irq_type_iosapic_edge;
|
||||
else
|
||||
return &irq_type_iosapic_level;
|
||||
}
|
||||
|
||||
static int
|
||||
register_intr (unsigned int gsi, int irq, unsigned char delivery,
|
||||
unsigned long polarity, unsigned long trigger)
|
||||
@@ -635,13 +644,10 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
|
||||
iosapic_intr_info[irq].dmode = delivery;
|
||||
iosapic_intr_info[irq].trigger = trigger;
|
||||
|
||||
if (trigger == IOSAPIC_EDGE)
|
||||
irq_type = &irq_type_iosapic_edge;
|
||||
else
|
||||
irq_type = &irq_type_iosapic_level;
|
||||
irq_type = iosapic_get_irq_chip(trigger);
|
||||
|
||||
idesc = irq_desc + irq;
|
||||
if (idesc->chip != irq_type) {
|
||||
if (irq_type != NULL && idesc->chip != irq_type) {
|
||||
if (idesc->chip != &no_irq_type)
|
||||
printk(KERN_WARNING
|
||||
"%s: changing vector %d from %s to %s\n",
|
||||
@@ -973,6 +979,22 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
|
||||
set_rte(gsi, irq, dest, 1);
|
||||
}
|
||||
|
||||
void __init
|
||||
ia64_native_iosapic_pcat_compat_init(void)
|
||||
{
|
||||
if (pcat_compat) {
|
||||
/*
|
||||
* Disable the compatibility mode interrupts (8259 style),
|
||||
* needs IN/OUT support enabled.
|
||||
*/
|
||||
printk(KERN_INFO
|
||||
"%s: Disabling PC-AT compatible 8259 interrupts\n",
|
||||
__func__);
|
||||
outb(0xff, 0xA1);
|
||||
outb(0xff, 0x21);
|
||||
}
|
||||
}
|
||||
|
||||
void __init
|
||||
iosapic_system_init (int system_pcat_compat)
|
||||
{
|
||||
@@ -987,17 +1009,8 @@ iosapic_system_init (int system_pcat_compat)
|
||||
}
|
||||
|
||||
pcat_compat = system_pcat_compat;
|
||||
if (pcat_compat) {
|
||||
/*
|
||||
* Disable the compatibility mode interrupts (8259 style),
|
||||
* needs IN/OUT support enabled.
|
||||
*/
|
||||
printk(KERN_INFO
|
||||
"%s: Disabling PC-AT compatible 8259 interrupts\n",
|
||||
__func__);
|
||||
outb(0xff, 0xA1);
|
||||
outb(0xff, 0x21);
|
||||
}
|
||||
if (pcat_compat)
|
||||
iosapic_pcat_compat_init();
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
||||
@@ -196,7 +196,7 @@ static void clear_irq_vector(int irq)
|
||||
}
|
||||
|
||||
int
|
||||
assign_irq_vector (int irq)
|
||||
ia64_native_assign_irq_vector (int irq)
|
||||
{
|
||||
unsigned long flags;
|
||||
int vector, cpu;
|
||||
@@ -222,7 +222,7 @@ assign_irq_vector (int irq)
|
||||
}
|
||||
|
||||
void
|
||||
free_irq_vector (int vector)
|
||||
ia64_native_free_irq_vector (int vector)
|
||||
{
|
||||
if (vector < IA64_FIRST_DEVICE_VECTOR ||
|
||||
vector > IA64_LAST_DEVICE_VECTOR)
|
||||
@@ -600,7 +600,6 @@ static irqreturn_t dummy_handler (int irq, void *dev_id)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
extern irqreturn_t handle_IPI (int irq, void *dev_id);
|
||||
|
||||
static struct irqaction ipi_irqaction = {
|
||||
.handler = handle_IPI,
|
||||
@@ -623,7 +622,7 @@ static struct irqaction tlb_irqaction = {
|
||||
#endif
|
||||
|
||||
void
|
||||
register_percpu_irq (ia64_vector vec, struct irqaction *action)
|
||||
ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
unsigned int irq;
|
||||
@@ -638,13 +637,21 @@ register_percpu_irq (ia64_vector vec, struct irqaction *action)
|
||||
}
|
||||
|
||||
void __init
|
||||
init_IRQ (void)
|
||||
ia64_native_register_ipi(void)
|
||||
{
|
||||
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
|
||||
#ifdef CONFIG_SMP
|
||||
register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
|
||||
register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
|
||||
register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init
|
||||
init_IRQ (void)
|
||||
{
|
||||
ia64_register_ipi();
|
||||
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
|
||||
#ifdef CONFIG_SMP
|
||||
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG)
|
||||
if (vector_domain_type != VECTOR_DOMAIN_NONE) {
|
||||
BUG_ON(IA64_FIRST_DEVICE_VECTOR != IA64_IRQ_MOVE_VECTOR);
|
||||
|
||||
+231
-231
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
#include <asm/cache.h>
|
||||
|
||||
#include "entry.h"
|
||||
#include "paravirt_inst.h"
|
||||
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
/* read ar.itc in advance, and use it before leaving bank 0 */
|
||||
@@ -43,16 +44,16 @@
|
||||
* Note that psr.ic is NOT turned on by this macro. This is so that
|
||||
* we can pass interruption state as arguments to a handler.
|
||||
*/
|
||||
#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA,WORKAROUND) \
|
||||
#define IA64_NATIVE_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND) \
|
||||
mov r16=IA64_KR(CURRENT); /* M */ \
|
||||
mov r27=ar.rsc; /* M */ \
|
||||
mov r20=r1; /* A */ \
|
||||
mov r25=ar.unat; /* M */ \
|
||||
mov r29=cr.ipsr; /* M */ \
|
||||
MOV_FROM_IPSR(p0,r29); /* M */ \
|
||||
mov r26=ar.pfs; /* I */ \
|
||||
mov r28=cr.iip; /* M */ \
|
||||
MOV_FROM_IIP(r28); /* M */ \
|
||||
mov r21=ar.fpsr; /* M */ \
|
||||
COVER; /* B;; (or nothing) */ \
|
||||
__COVER; /* B;; (or nothing) */ \
|
||||
;; \
|
||||
adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \
|
||||
;; \
|
||||
@@ -244,6 +245,6 @@
|
||||
1: \
|
||||
.pred.rel "mutex", pKStk, pUStk
|
||||
|
||||
#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs, , RSE_WORKAROUND)
|
||||
#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND)
|
||||
#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(COVER, mov r30=cr.ifs, , RSE_WORKAROUND)
|
||||
#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(COVER, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND)
|
||||
#define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, , )
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* calculate
|
||||
* NR_IRQS = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, FOO_NR_IRQS...)
|
||||
* depending on config.
|
||||
* This must be calculated before processing asm-offset.c.
|
||||
*/
|
||||
|
||||
#define ASM_OFFSETS_C 1
|
||||
|
||||
#include <linux/kbuild.h>
|
||||
#include <linux/threads.h>
|
||||
#include <asm-ia64/native/irq.h>
|
||||
|
||||
void foo(void)
|
||||
{
|
||||
union paravirt_nr_irqs_max {
|
||||
char ia64_native_nr_irqs[IA64_NATIVE_NR_IRQS];
|
||||
#ifdef CONFIG_XEN
|
||||
char xen_nr_irqs[XEN_NR_IRQS];
|
||||
#endif
|
||||
};
|
||||
|
||||
DEFINE(NR_IRQS, sizeof (union paravirt_nr_irqs_max));
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/******************************************************************************
|
||||
* arch/ia64/kernel/paravirt.c
|
||||
*
|
||||
* Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
|
||||
* VA Linux Systems Japan K.K.
|
||||
* Yaozu (Eddie) Dong <eddie.dong@intel.com>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/iosapic.h>
|
||||
#include <asm/paravirt.h>
|
||||
|
||||
/***************************************************************************
|
||||
* general info
|
||||
*/
|
||||
struct pv_info pv_info = {
|
||||
.kernel_rpl = 0,
|
||||
.paravirt_enabled = 0,
|
||||
.name = "bare hardware"
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* pv_init_ops
|
||||
* initialization hooks.
|
||||
*/
|
||||
|
||||
struct pv_init_ops pv_init_ops;
|
||||
|
||||
/***************************************************************************
|
||||
* pv_cpu_ops
|
||||
* intrinsics hooks.
|
||||
*/
|
||||
|
||||
/* ia64_native_xxx are macros so that we have to make them real functions */
|
||||
|
||||
#define DEFINE_VOID_FUNC1(name) \
|
||||
static void \
|
||||
ia64_native_ ## name ## _func(unsigned long arg) \
|
||||
{ \
|
||||
ia64_native_ ## name(arg); \
|
||||
} \
|
||||
|
||||
#define DEFINE_VOID_FUNC2(name) \
|
||||
static void \
|
||||
ia64_native_ ## name ## _func(unsigned long arg0, \
|
||||
unsigned long arg1) \
|
||||
{ \
|
||||
ia64_native_ ## name(arg0, arg1); \
|
||||
} \
|
||||
|
||||
#define DEFINE_FUNC0(name) \
|
||||
static unsigned long \
|
||||
ia64_native_ ## name ## _func(void) \
|
||||
{ \
|
||||
return ia64_native_ ## name(); \
|
||||
}
|
||||
|
||||
#define DEFINE_FUNC1(name, type) \
|
||||
static unsigned long \
|
||||
ia64_native_ ## name ## _func(type arg) \
|
||||
{ \
|
||||
return ia64_native_ ## name(arg); \
|
||||
} \
|
||||
|
||||
DEFINE_VOID_FUNC1(fc);
|
||||
DEFINE_VOID_FUNC1(intrin_local_irq_restore);
|
||||
|
||||
DEFINE_VOID_FUNC2(ptcga);
|
||||
DEFINE_VOID_FUNC2(set_rr);
|
||||
|
||||
DEFINE_FUNC0(get_psr_i);
|
||||
|
||||
DEFINE_FUNC1(thash, unsigned long);
|
||||
DEFINE_FUNC1(get_cpuid, int);
|
||||
DEFINE_FUNC1(get_pmd, int);
|
||||
DEFINE_FUNC1(get_rr, unsigned long);
|
||||
|
||||
static void
|
||||
ia64_native_ssm_i_func(void)
|
||||
{
|
||||
ia64_native_ssm(IA64_PSR_I);
|
||||
}
|
||||
|
||||
static void
|
||||
ia64_native_rsm_i_func(void)
|
||||
{
|
||||
ia64_native_rsm(IA64_PSR_I);
|
||||
}
|
||||
|
||||
static void
|
||||
ia64_native_set_rr0_to_rr4_func(unsigned long val0, unsigned long val1,
|
||||
unsigned long val2, unsigned long val3,
|
||||
unsigned long val4)
|
||||
{
|
||||
ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4);
|
||||
}
|
||||
|
||||
#define CASE_GET_REG(id) \
|
||||
case _IA64_REG_ ## id: \
|
||||
res = ia64_native_getreg(_IA64_REG_ ## id); \
|
||||
break;
|
||||
#define CASE_GET_AR(id) CASE_GET_REG(AR_ ## id)
|
||||
#define CASE_GET_CR(id) CASE_GET_REG(CR_ ## id)
|
||||
|
||||
unsigned long
|
||||
ia64_native_getreg_func(int regnum)
|
||||
{
|
||||
unsigned long res = -1;
|
||||
switch (regnum) {
|
||||
CASE_GET_REG(GP);
|
||||
CASE_GET_REG(IP);
|
||||
CASE_GET_REG(PSR);
|
||||
CASE_GET_REG(TP);
|
||||
CASE_GET_REG(SP);
|
||||
|
||||
CASE_GET_AR(KR0);
|
||||
CASE_GET_AR(KR1);
|
||||
CASE_GET_AR(KR2);
|
||||
CASE_GET_AR(KR3);
|
||||
CASE_GET_AR(KR4);
|
||||
CASE_GET_AR(KR5);
|
||||
CASE_GET_AR(KR6);
|
||||
CASE_GET_AR(KR7);
|
||||
CASE_GET_AR(RSC);
|
||||
CASE_GET_AR(BSP);
|
||||
CASE_GET_AR(BSPSTORE);
|
||||
CASE_GET_AR(RNAT);
|
||||
CASE_GET_AR(FCR);
|
||||
CASE_GET_AR(EFLAG);
|
||||
CASE_GET_AR(CSD);
|
||||
CASE_GET_AR(SSD);
|
||||
CASE_GET_AR(CFLAG);
|
||||
CASE_GET_AR(FSR);
|
||||
CASE_GET_AR(FIR);
|
||||
CASE_GET_AR(FDR);
|
||||
CASE_GET_AR(CCV);
|
||||
CASE_GET_AR(UNAT);
|
||||
CASE_GET_AR(FPSR);
|
||||
CASE_GET_AR(ITC);
|
||||
CASE_GET_AR(PFS);
|
||||
CASE_GET_AR(LC);
|
||||
CASE_GET_AR(EC);
|
||||
|
||||
CASE_GET_CR(DCR);
|
||||
CASE_GET_CR(ITM);
|
||||
CASE_GET_CR(IVA);
|
||||
CASE_GET_CR(PTA);
|
||||
CASE_GET_CR(IPSR);
|
||||
CASE_GET_CR(ISR);
|
||||
CASE_GET_CR(IIP);
|
||||
CASE_GET_CR(IFA);
|
||||
CASE_GET_CR(ITIR);
|
||||
CASE_GET_CR(IIPA);
|
||||
CASE_GET_CR(IFS);
|
||||
CASE_GET_CR(IIM);
|
||||
CASE_GET_CR(IHA);
|
||||
CASE_GET_CR(LID);
|
||||
CASE_GET_CR(IVR);
|
||||
CASE_GET_CR(TPR);
|
||||
CASE_GET_CR(EOI);
|
||||
CASE_GET_CR(IRR0);
|
||||
CASE_GET_CR(IRR1);
|
||||
CASE_GET_CR(IRR2);
|
||||
CASE_GET_CR(IRR3);
|
||||
CASE_GET_CR(ITV);
|
||||
CASE_GET_CR(PMV);
|
||||
CASE_GET_CR(CMCV);
|
||||
CASE_GET_CR(LRR0);
|
||||
CASE_GET_CR(LRR1);
|
||||
|
||||
default:
|
||||
printk(KERN_CRIT "wrong_getreg %d\n", regnum);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#define CASE_SET_REG(id) \
|
||||
case _IA64_REG_ ## id: \
|
||||
ia64_native_setreg(_IA64_REG_ ## id, val); \
|
||||
break;
|
||||
#define CASE_SET_AR(id) CASE_SET_REG(AR_ ## id)
|
||||
#define CASE_SET_CR(id) CASE_SET_REG(CR_ ## id)
|
||||
|
||||
void
|
||||
ia64_native_setreg_func(int regnum, unsigned long val)
|
||||
{
|
||||
switch (regnum) {
|
||||
case _IA64_REG_PSR_L:
|
||||
ia64_native_setreg(_IA64_REG_PSR_L, val);
|
||||
ia64_dv_serialize_data();
|
||||
break;
|
||||
CASE_SET_REG(SP);
|
||||
CASE_SET_REG(GP);
|
||||
|
||||
CASE_SET_AR(KR0);
|
||||
CASE_SET_AR(KR1);
|
||||
CASE_SET_AR(KR2);
|
||||
CASE_SET_AR(KR3);
|
||||
CASE_SET_AR(KR4);
|
||||
CASE_SET_AR(KR5);
|
||||
CASE_SET_AR(KR6);
|
||||
CASE_SET_AR(KR7);
|
||||
CASE_SET_AR(RSC);
|
||||
CASE_SET_AR(BSP);
|
||||
CASE_SET_AR(BSPSTORE);
|
||||
CASE_SET_AR(RNAT);
|
||||
CASE_SET_AR(FCR);
|
||||
CASE_SET_AR(EFLAG);
|
||||
CASE_SET_AR(CSD);
|
||||
CASE_SET_AR(SSD);
|
||||
CASE_SET_AR(CFLAG);
|
||||
CASE_SET_AR(FSR);
|
||||
CASE_SET_AR(FIR);
|
||||
CASE_SET_AR(FDR);
|
||||
CASE_SET_AR(CCV);
|
||||
CASE_SET_AR(UNAT);
|
||||
CASE_SET_AR(FPSR);
|
||||
CASE_SET_AR(ITC);
|
||||
CASE_SET_AR(PFS);
|
||||
CASE_SET_AR(LC);
|
||||
CASE_SET_AR(EC);
|
||||
|
||||
CASE_SET_CR(DCR);
|
||||
CASE_SET_CR(ITM);
|
||||
CASE_SET_CR(IVA);
|
||||
CASE_SET_CR(PTA);
|
||||
CASE_SET_CR(IPSR);
|
||||
CASE_SET_CR(ISR);
|
||||
CASE_SET_CR(IIP);
|
||||
CASE_SET_CR(IFA);
|
||||
CASE_SET_CR(ITIR);
|
||||
CASE_SET_CR(IIPA);
|
||||
CASE_SET_CR(IFS);
|
||||
CASE_SET_CR(IIM);
|
||||
CASE_SET_CR(IHA);
|
||||
CASE_SET_CR(LID);
|
||||
CASE_SET_CR(IVR);
|
||||
CASE_SET_CR(TPR);
|
||||
CASE_SET_CR(EOI);
|
||||
CASE_SET_CR(IRR0);
|
||||
CASE_SET_CR(IRR1);
|
||||
CASE_SET_CR(IRR2);
|
||||
CASE_SET_CR(IRR3);
|
||||
CASE_SET_CR(ITV);
|
||||
CASE_SET_CR(PMV);
|
||||
CASE_SET_CR(CMCV);
|
||||
CASE_SET_CR(LRR0);
|
||||
CASE_SET_CR(LRR1);
|
||||
default:
|
||||
printk(KERN_CRIT "wrong setreg %d\n", regnum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct pv_cpu_ops pv_cpu_ops = {
|
||||
.fc = ia64_native_fc_func,
|
||||
.thash = ia64_native_thash_func,
|
||||
.get_cpuid = ia64_native_get_cpuid_func,
|
||||
.get_pmd = ia64_native_get_pmd_func,
|
||||
.ptcga = ia64_native_ptcga_func,
|
||||
.get_rr = ia64_native_get_rr_func,
|
||||
.set_rr = ia64_native_set_rr_func,
|
||||
.set_rr0_to_rr4 = ia64_native_set_rr0_to_rr4_func,
|
||||
.ssm_i = ia64_native_ssm_i_func,
|
||||
.getreg = ia64_native_getreg_func,
|
||||
.setreg = ia64_native_setreg_func,
|
||||
.rsm_i = ia64_native_rsm_i_func,
|
||||
.get_psr_i = ia64_native_get_psr_i_func,
|
||||
.intrin_local_irq_restore
|
||||
= ia64_native_intrin_local_irq_restore_func,
|
||||
};
|
||||
EXPORT_SYMBOL(pv_cpu_ops);
|
||||
|
||||
/******************************************************************************
|
||||
* replacement of hand written assembly codes.
|
||||
*/
|
||||
|
||||
void
|
||||
paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch)
|
||||
{
|
||||
extern unsigned long paravirt_switch_to_targ;
|
||||
extern unsigned long paravirt_leave_syscall_targ;
|
||||
extern unsigned long paravirt_work_processed_syscall_targ;
|
||||
extern unsigned long paravirt_leave_kernel_targ;
|
||||
|
||||
paravirt_switch_to_targ = cpu_asm_switch->switch_to;
|
||||
paravirt_leave_syscall_targ = cpu_asm_switch->leave_syscall;
|
||||
paravirt_work_processed_syscall_targ =
|
||||
cpu_asm_switch->work_processed_syscall;
|
||||
paravirt_leave_kernel_targ = cpu_asm_switch->leave_kernel;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* pv_iosapic_ops
|
||||
* iosapic read/write hooks.
|
||||
*/
|
||||
|
||||
static unsigned int
|
||||
ia64_native_iosapic_read(char __iomem *iosapic, unsigned int reg)
|
||||
{
|
||||
return __ia64_native_iosapic_read(iosapic, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
|
||||
{
|
||||
__ia64_native_iosapic_write(iosapic, reg, val);
|
||||
}
|
||||
|
||||
struct pv_iosapic_ops pv_iosapic_ops = {
|
||||
.pcat_compat_init = ia64_native_iosapic_pcat_compat_init,
|
||||
.get_irq_chip = ia64_native_iosapic_get_irq_chip,
|
||||
|
||||
.__read = ia64_native_iosapic_read,
|
||||
.__write = ia64_native_iosapic_write,
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* pv_irq_ops
|
||||
* irq operations
|
||||
*/
|
||||
|
||||
struct pv_irq_ops pv_irq_ops = {
|
||||
.register_ipi = ia64_native_register_ipi,
|
||||
|
||||
.assign_irq_vector = ia64_native_assign_irq_vector,
|
||||
.free_irq_vector = ia64_native_free_irq_vector,
|
||||
.register_percpu_irq = ia64_native_register_percpu_irq,
|
||||
|
||||
.resend_irq = ia64_native_resend_irq,
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* pv_time_ops
|
||||
* time operations
|
||||
*/
|
||||
|
||||
static int
|
||||
ia64_native_do_steal_accounting(unsigned long *new_itm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pv_time_ops pv_time_ops = {
|
||||
.do_steal_accounting = ia64_native_do_steal_accounting,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
/******************************************************************************
|
||||
* linux/arch/ia64/xen/paravirt_inst.h
|
||||
*
|
||||
* Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
|
||||
* VA Linux Systems Japan K.K.
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __IA64_ASM_PARAVIRTUALIZED_XEN
|
||||
#include <asm/xen/inst.h>
|
||||
#include <asm/xen/minstate.h>
|
||||
#else
|
||||
#include <asm/native/inst.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/******************************************************************************
|
||||
* linux/arch/ia64/xen/paravirtentry.S
|
||||
*
|
||||
* Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
|
||||
* VA Linux Systems Japan K.K.
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include "entry.h"
|
||||
|
||||
#define DATA8(sym, init_value) \
|
||||
.pushsection .data.read_mostly ; \
|
||||
.align 8 ; \
|
||||
.global sym ; \
|
||||
sym: ; \
|
||||
data8 init_value ; \
|
||||
.popsection
|
||||
|
||||
#define BRANCH(targ, reg, breg) \
|
||||
movl reg=targ ; \
|
||||
;; \
|
||||
ld8 reg=[reg] ; \
|
||||
;; \
|
||||
mov breg=reg ; \
|
||||
br.cond.sptk.many breg
|
||||
|
||||
#define BRANCH_PROC(sym, reg, breg) \
|
||||
DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \
|
||||
GLOBAL_ENTRY(paravirt_ ## sym) ; \
|
||||
BRANCH(paravirt_ ## sym ## _targ, reg, breg) ; \
|
||||
END(paravirt_ ## sym)
|
||||
|
||||
#define BRANCH_PROC_UNWINFO(sym, reg, breg) \
|
||||
DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \
|
||||
GLOBAL_ENTRY(paravirt_ ## sym) ; \
|
||||
PT_REGS_UNWIND_INFO(0) ; \
|
||||
BRANCH(paravirt_ ## sym ## _targ, reg, breg) ; \
|
||||
END(paravirt_ ## sym)
|
||||
|
||||
|
||||
BRANCH_PROC(switch_to, r22, b7)
|
||||
BRANCH_PROC_UNWINFO(leave_syscall, r22, b7)
|
||||
BRANCH_PROC(work_processed_syscall, r2, b7)
|
||||
BRANCH_PROC_UNWINFO(leave_kernel, r22, b7)
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <asm/mca.h>
|
||||
#include <asm/meminit.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/patch.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -341,6 +342,8 @@ reserve_memory (void)
|
||||
rsvd_region[n].end = (unsigned long) ia64_imva(_end);
|
||||
n++;
|
||||
|
||||
n += paravirt_reserve_memory(&rsvd_region[n]);
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (ia64_boot_param->initrd_start) {
|
||||
rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start);
|
||||
@@ -519,6 +522,8 @@ setup_arch (char **cmdline_p)
|
||||
{
|
||||
unw_init();
|
||||
|
||||
paravirt_arch_setup_early();
|
||||
|
||||
ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
|
||||
|
||||
*cmdline_p = __va(ia64_boot_param->command_line);
|
||||
@@ -583,6 +588,9 @@ setup_arch (char **cmdline_p)
|
||||
acpi_boot_init();
|
||||
#endif
|
||||
|
||||
paravirt_banner();
|
||||
paravirt_arch_setup_console(cmdline_p);
|
||||
|
||||
#ifdef CONFIG_VT
|
||||
if (!conswitchp) {
|
||||
# if defined(CONFIG_DUMMY_CONSOLE)
|
||||
@@ -602,6 +610,8 @@ setup_arch (char **cmdline_p)
|
||||
#endif
|
||||
|
||||
/* enable IA-64 Machine Check Abort Handling unless disabled */
|
||||
if (paravirt_arch_setup_nomca())
|
||||
nomca = 1;
|
||||
if (!nomca)
|
||||
ia64_mca_init();
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/mca.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -642,6 +643,7 @@ void __devinit smp_prepare_boot_cpu(void)
|
||||
cpu_set(smp_processor_id(), cpu_online_map);
|
||||
cpu_set(smp_processor_id(), cpu_callin_map);
|
||||
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
|
||||
paravirt_post_smp_prepare_boot_cpu();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/sal.h>
|
||||
#include <asm/sections.h>
|
||||
@@ -48,6 +49,15 @@ EXPORT_SYMBOL(last_cli_ip);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
static void
|
||||
paravirt_clocksource_resume(void)
|
||||
{
|
||||
if (pv_time_ops.clocksource_resume)
|
||||
pv_time_ops.clocksource_resume();
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct clocksource clocksource_itc = {
|
||||
.name = "itc",
|
||||
.rating = 350,
|
||||
@@ -56,6 +66,9 @@ static struct clocksource clocksource_itc = {
|
||||
.mult = 0, /*to be calculated*/
|
||||
.shift = 16,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
.resume = paravirt_clocksource_resume,
|
||||
#endif
|
||||
};
|
||||
static struct clocksource *itc_clocksource;
|
||||
|
||||
@@ -157,6 +170,9 @@ timer_interrupt (int irq, void *dev_id)
|
||||
|
||||
profile_tick(CPU_PROFILING);
|
||||
|
||||
if (paravirt_do_steal_accounting(&new_itm))
|
||||
goto skip_process_time_accounting;
|
||||
|
||||
while (1) {
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
|
||||
@@ -186,6 +202,8 @@ timer_interrupt (int irq, void *dev_id)
|
||||
local_irq_disable();
|
||||
}
|
||||
|
||||
skip_process_time_accounting:
|
||||
|
||||
do {
|
||||
/*
|
||||
* If we're too close to the next clock tick for
|
||||
@@ -335,6 +353,11 @@ ia64_init_itm (void)
|
||||
*/
|
||||
clocksource_itc.rating = 50;
|
||||
|
||||
paravirt_init_missing_ticks_accounting(smp_processor_id());
|
||||
|
||||
/* avoid softlock up message when cpu is unplug and plugged again. */
|
||||
touch_softlockup_watchdog();
|
||||
|
||||
/* Setup the CPU local timer tick */
|
||||
ia64_cpu_local_tick();
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
#define LOAD_OFFSET (KERNEL_START - KERNEL_TR_PAGE_SIZE)
|
||||
#include <asm-generic/vmlinux.lds.h>
|
||||
|
||||
#define IVT_TEXT \
|
||||
|
||||
@@ -5,12 +5,12 @@ header-y += fpu.h
|
||||
header-y += fpswa.h
|
||||
header-y += ia64regs.h
|
||||
header-y += intel_intrin.h
|
||||
header-y += intrinsics.h
|
||||
header-y += perfmon_default_smpl.h
|
||||
header-y += ptrace_offsets.h
|
||||
header-y += rse.h
|
||||
header-y += ucontext.h
|
||||
|
||||
unifdef-y += gcc_intrin.h
|
||||
unifdef-y += intrinsics.h
|
||||
unifdef-y += perfmon.h
|
||||
unifdef-y += ustack.h
|
||||
|
||||
@@ -32,7 +32,7 @@ extern void ia64_bad_param_for_getreg (void);
|
||||
register unsigned long ia64_r13 asm ("r13") __used;
|
||||
#endif
|
||||
|
||||
#define ia64_setreg(regnum, val) \
|
||||
#define ia64_native_setreg(regnum, val) \
|
||||
({ \
|
||||
switch (regnum) { \
|
||||
case _IA64_REG_PSR_L: \
|
||||
@@ -61,7 +61,7 @@ register unsigned long ia64_r13 asm ("r13") __used;
|
||||
} \
|
||||
})
|
||||
|
||||
#define ia64_getreg(regnum) \
|
||||
#define ia64_native_getreg(regnum) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
\
|
||||
@@ -385,7 +385,7 @@ register unsigned long ia64_r13 asm ("r13") __used;
|
||||
|
||||
#define ia64_invala() asm volatile ("invala" ::: "memory")
|
||||
|
||||
#define ia64_thash(addr) \
|
||||
#define ia64_native_thash(addr) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \
|
||||
@@ -438,10 +438,10 @@ register unsigned long ia64_r13 asm ("r13") __used;
|
||||
#define ia64_set_pmd(index, val) \
|
||||
asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
|
||||
|
||||
#define ia64_set_rr(index, val) \
|
||||
#define ia64_native_set_rr(index, val) \
|
||||
asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
|
||||
|
||||
#define ia64_get_cpuid(index) \
|
||||
#define ia64_native_get_cpuid(index) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index)); \
|
||||
@@ -477,33 +477,33 @@ register unsigned long ia64_r13 asm ("r13") __used;
|
||||
})
|
||||
|
||||
|
||||
#define ia64_get_pmd(index) \
|
||||
#define ia64_native_get_pmd(index) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
|
||||
ia64_intri_res; \
|
||||
})
|
||||
|
||||
#define ia64_get_rr(index) \
|
||||
#define ia64_native_get_rr(index) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index)); \
|
||||
ia64_intri_res; \
|
||||
})
|
||||
|
||||
#define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
|
||||
#define ia64_native_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
|
||||
|
||||
|
||||
#define ia64_sync_i() asm volatile (";; sync.i" ::: "memory")
|
||||
|
||||
#define ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
|
||||
#define ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
|
||||
#define ia64_native_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
|
||||
#define ia64_native_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
|
||||
#define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory")
|
||||
#define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory")
|
||||
|
||||
#define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr))
|
||||
|
||||
#define ia64_ptcga(addr, size) \
|
||||
#define ia64_native_ptcga(addr, size) \
|
||||
do { \
|
||||
asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \
|
||||
ia64_dv_serialize_data(); \
|
||||
@@ -608,7 +608,7 @@ do { \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ia64_intrin_local_irq_restore(x) \
|
||||
#define ia64_native_intrin_local_irq_restore(x) \
|
||||
do { \
|
||||
asm volatile (";; cmp.ne p6,p7=%0,r0;;" \
|
||||
"(p6) ssm psr.i;" \
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#ifndef CONFIG_PARAVIRT
|
||||
typedef u8 ia64_vector;
|
||||
#else
|
||||
typedef u16 ia64_vector;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 0 special
|
||||
@@ -104,13 +108,24 @@ DECLARE_PER_CPU(int[IA64_NUM_VECTORS], vector_irq);
|
||||
|
||||
extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */
|
||||
|
||||
#ifdef CONFIG_PARAVIRT_GUEST
|
||||
#include <asm/paravirt.h>
|
||||
#else
|
||||
#define ia64_register_ipi ia64_native_register_ipi
|
||||
#define assign_irq_vector ia64_native_assign_irq_vector
|
||||
#define free_irq_vector ia64_native_free_irq_vector
|
||||
#define register_percpu_irq ia64_native_register_percpu_irq
|
||||
#define ia64_resend_irq ia64_native_resend_irq
|
||||
#endif
|
||||
|
||||
extern void ia64_native_register_ipi(void);
|
||||
extern int bind_irq_vector(int irq, int vector, cpumask_t domain);
|
||||
extern int assign_irq_vector (int irq); /* allocate a free vector */
|
||||
extern void free_irq_vector (int vector);
|
||||
extern int ia64_native_assign_irq_vector (int irq); /* allocate a free vector */
|
||||
extern void ia64_native_free_irq_vector (int vector);
|
||||
extern int reserve_irq_vector (int vector);
|
||||
extern void __setup_vector_irq(int cpu);
|
||||
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
|
||||
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
|
||||
extern void ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action);
|
||||
extern int check_irq_used (int irq);
|
||||
extern void destroy_and_reserve_irq (unsigned int irq);
|
||||
|
||||
@@ -122,7 +137,7 @@ static inline int irq_prepare_move(int irq, int cpu) { return 0; }
|
||||
static inline void irq_complete_move(unsigned int irq) {}
|
||||
#endif
|
||||
|
||||
static inline void ia64_resend_irq(unsigned int vector)
|
||||
static inline void ia64_native_resend_irq(unsigned int vector)
|
||||
{
|
||||
platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user