mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-12 08:00:09 +00:00
Merge branch 'fixes' into next
Merge in our fixes branch. In particular we want to merge the TM and KUAP fixes, so we can add selftests for them in next.
This commit is contained in:
commit
819723a8a2
@ -295,8 +295,13 @@ static inline bool pfn_valid(unsigned long pfn)
|
||||
/*
|
||||
* Some number of bits at the level of the page table that points to
|
||||
* a hugepte are used to encode the size. This masks those bits.
|
||||
* On 8xx, HW assistance requires 4k alignment for the hugepte.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
#define HUGEPD_SHIFT_MASK 0xfff
|
||||
#else
|
||||
#define HUGEPD_SHIFT_MASK 0x3f
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
|
@ -168,6 +168,10 @@ struct thread_struct {
|
||||
unsigned long srr1;
|
||||
unsigned long dar;
|
||||
unsigned long dsisr;
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
unsigned long r0, r3, r4, r5, r6, r8, r9, r11;
|
||||
unsigned long lr, ctr;
|
||||
#endif
|
||||
#endif
|
||||
/* Debug Registers */
|
||||
struct debug_reg debug;
|
||||
|
@ -132,6 +132,18 @@ int main(void)
|
||||
OFFSET(SRR1, thread_struct, srr1);
|
||||
OFFSET(DAR, thread_struct, dar);
|
||||
OFFSET(DSISR, thread_struct, dsisr);
|
||||
#ifdef CONFIG_PPC_BOOK3S_32
|
||||
OFFSET(THR0, thread_struct, r0);
|
||||
OFFSET(THR3, thread_struct, r3);
|
||||
OFFSET(THR4, thread_struct, r4);
|
||||
OFFSET(THR5, thread_struct, r5);
|
||||
OFFSET(THR6, thread_struct, r6);
|
||||
OFFSET(THR8, thread_struct, r8);
|
||||
OFFSET(THR9, thread_struct, r9);
|
||||
OFFSET(THR11, thread_struct, r11);
|
||||
OFFSET(THLR, thread_struct, lr);
|
||||
OFFSET(THCTR, thread_struct, ctr);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_SPE
|
||||
OFFSET(THREAD_EVR0, thread_struct, evr[0]);
|
||||
|
@ -2193,11 +2193,13 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset,
|
||||
* oprofile_cpu_type already has a value, then we are
|
||||
* possibly overriding a real PVR with a logical one,
|
||||
* and, in that case, keep the current value for
|
||||
* oprofile_cpu_type.
|
||||
* oprofile_cpu_type. Futhermore, let's ensure that the
|
||||
* fix for the PMAO bug is enabled on compatibility mode.
|
||||
*/
|
||||
if (old.oprofile_cpu_type != NULL) {
|
||||
t->oprofile_cpu_type = old.oprofile_cpu_type;
|
||||
t->oprofile_type = old.oprofile_type;
|
||||
t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1184,6 +1184,17 @@ void eeh_handle_special_event(void)
|
||||
eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
|
||||
eeh_handle_normal_event(pe);
|
||||
} else {
|
||||
eeh_for_each_pe(pe, tmp_pe)
|
||||
eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
|
||||
edev->mode &= ~EEH_DEV_NO_HANDLER;
|
||||
|
||||
/* Notify all devices to be down */
|
||||
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
|
||||
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
|
||||
eeh_pe_report(
|
||||
"error_detected(permanent failure)", pe,
|
||||
eeh_report_failure, NULL);
|
||||
|
||||
pci_lock_rescan_remove();
|
||||
list_for_each_entry(hose, &hose_list, list_node) {
|
||||
phb_pe = eeh_phb_pe_get(hose);
|
||||
@ -1192,16 +1203,6 @@ void eeh_handle_special_event(void)
|
||||
(phb_pe->state & EEH_PE_RECOVERING))
|
||||
continue;
|
||||
|
||||
eeh_for_each_pe(pe, tmp_pe)
|
||||
eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
|
||||
edev->mode &= ~EEH_DEV_NO_HANDLER;
|
||||
|
||||
/* Notify all devices to be down */
|
||||
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
|
||||
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
|
||||
eeh_pe_report(
|
||||
"error_detected(permanent failure)", pe,
|
||||
eeh_report_failure, NULL);
|
||||
bus = eeh_pe_bus_get(phb_pe);
|
||||
if (!bus) {
|
||||
pr_err("%s: Cannot find PCI bus for "
|
||||
|
@ -805,7 +805,7 @@ fast_exception_return:
|
||||
1: lis r3,exc_exit_restart_end@ha
|
||||
addi r3,r3,exc_exit_restart_end@l
|
||||
cmplw r12,r3
|
||||
#if CONFIG_PPC_BOOK3S_601
|
||||
#ifdef CONFIG_PPC_BOOK3S_601
|
||||
bge 2b
|
||||
#else
|
||||
bge 3f
|
||||
@ -813,7 +813,7 @@ fast_exception_return:
|
||||
lis r4,exc_exit_restart@ha
|
||||
addi r4,r4,exc_exit_restart@l
|
||||
cmplw r12,r4
|
||||
#if CONFIG_PPC_BOOK3S_601
|
||||
#ifdef CONFIG_PPC_BOOK3S_601
|
||||
blt 2b
|
||||
#else
|
||||
blt 3f
|
||||
@ -1376,12 +1376,17 @@ _GLOBAL(enter_rtas)
|
||||
mtspr SPRN_SRR0,r8
|
||||
mtspr SPRN_SRR1,r9
|
||||
RFI
|
||||
1: tophys(r9,r1)
|
||||
1: tophys_novmstack r9, r1
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
li r0, MSR_KERNEL & ~MSR_IR /* can take DTLB miss */
|
||||
mtmsr r0
|
||||
isync
|
||||
#endif
|
||||
lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
|
||||
lwz r9,8(r9) /* original msr value */
|
||||
addi r1,r1,INT_FRAME_SIZE
|
||||
li r0,0
|
||||
tophys(r7, r2)
|
||||
tophys_novmstack r7, r2
|
||||
stw r0, THREAD + RTAS_SP(r7)
|
||||
mtspr SPRN_SRR0,r8
|
||||
mtspr SPRN_SRR1,r9
|
||||
|
@ -290,17 +290,55 @@ MachineCheck:
|
||||
7: EXCEPTION_PROLOG_2
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
bne cr1,1f
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mfspr r4, SPRN_SPRG_THREAD
|
||||
tovirt(r4, r4)
|
||||
lwz r4, RTAS_SP(r4)
|
||||
cmpwi cr1, r4, 0
|
||||
#endif
|
||||
EXC_XFER_STD(0x200, machine_check_exception)
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
1: b machine_check_in_rtas
|
||||
beq cr1, machine_check_tramp
|
||||
b machine_check_in_rtas
|
||||
#else
|
||||
b machine_check_tramp
|
||||
#endif
|
||||
|
||||
/* Data access exception. */
|
||||
. = 0x300
|
||||
DO_KVM 0x300
|
||||
DataAccess:
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mtspr SPRN_SPRG_SCRATCH0,r10
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
stw r11, THR11(r10)
|
||||
mfspr r10, SPRN_DSISR
|
||||
mfcr r11
|
||||
#ifdef CONFIG_PPC_KUAP
|
||||
andis. r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
|
||||
#else
|
||||
andis. r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
|
||||
#endif
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
beq hash_page_dsi
|
||||
.Lhash_page_dsi_cont:
|
||||
mtcr r11
|
||||
lwz r11, THR11(r10)
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
mtspr SPRN_SPRG_SCRATCH1,r11
|
||||
mfspr r11, SPRN_DAR
|
||||
stw r11, DAR(r10)
|
||||
mfspr r11, SPRN_DSISR
|
||||
stw r11, DSISR(r10)
|
||||
mfspr r11, SPRN_SRR0
|
||||
stw r11, SRR0(r10)
|
||||
mfspr r11, SPRN_SRR1 /* check whether user or kernel */
|
||||
stw r11, SRR1(r10)
|
||||
mfcr r10
|
||||
andi. r11, r11, MSR_PR
|
||||
|
||||
EXCEPTION_PROLOG_1
|
||||
b handle_page_fault_tramp_1
|
||||
#else /* CONFIG_VMAP_STACK */
|
||||
EXCEPTION_PROLOG handle_dar_dsisr=1
|
||||
get_and_save_dar_dsisr_on_stack r4, r5, r11
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
@ -316,11 +354,32 @@ BEGIN_MMU_FTR_SECTION
|
||||
FTR_SECTION_ELSE
|
||||
b handle_page_fault_tramp_2
|
||||
ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#endif /* CONFIG_VMAP_STACK */
|
||||
|
||||
/* Instruction access exception. */
|
||||
. = 0x400
|
||||
DO_KVM 0x400
|
||||
InstructionAccess:
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
mtspr SPRN_SPRG_SCRATCH0,r10
|
||||
mtspr SPRN_SPRG_SCRATCH1,r11
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
mfspr r11, SPRN_SRR0
|
||||
stw r11, SRR0(r10)
|
||||
mfspr r11, SPRN_SRR1 /* check whether user or kernel */
|
||||
stw r11, SRR1(r10)
|
||||
mfcr r10
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
andis. r11, r11, SRR1_ISI_NOPT@h /* no pte found? */
|
||||
bne hash_page_isi
|
||||
.Lhash_page_isi_cont:
|
||||
mfspr r11, SPRN_SRR1 /* check whether user or kernel */
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
andi. r11, r11, MSR_PR
|
||||
|
||||
EXCEPTION_PROLOG_1
|
||||
EXCEPTION_PROLOG_2
|
||||
#else /* CONFIG_VMAP_STACK */
|
||||
EXCEPTION_PROLOG
|
||||
andis. r0,r9,SRR1_ISI_NOPT@h /* no pte found? */
|
||||
beq 1f /* if so, try to put a PTE */
|
||||
@ -329,6 +388,7 @@ InstructionAccess:
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
bl hash_page
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#endif /* CONFIG_VMAP_STACK */
|
||||
1: mr r4,r12
|
||||
andis. r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
|
||||
stw r4, _DAR(r11)
|
||||
@ -344,7 +404,7 @@ Alignment:
|
||||
EXCEPTION_PROLOG handle_dar_dsisr=1
|
||||
save_dar_dsisr_on_stack r4, r5, r11
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
EXC_XFER_STD(0x600, alignment_exception)
|
||||
b alignment_exception_tramp
|
||||
|
||||
/* Program check exception */
|
||||
EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
|
||||
@ -645,15 +705,100 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
|
||||
|
||||
. = 0x3000
|
||||
|
||||
machine_check_tramp:
|
||||
EXC_XFER_STD(0x200, machine_check_exception)
|
||||
|
||||
alignment_exception_tramp:
|
||||
EXC_XFER_STD(0x600, alignment_exception)
|
||||
|
||||
handle_page_fault_tramp_1:
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
EXCEPTION_PROLOG_2 handle_dar_dsisr=1
|
||||
#endif
|
||||
lwz r4, _DAR(r11)
|
||||
lwz r5, _DSISR(r11)
|
||||
/* fall through */
|
||||
handle_page_fault_tramp_2:
|
||||
EXC_XFER_LITE(0x300, handle_page_fault)
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
.macro save_regs_thread thread
|
||||
stw r0, THR0(\thread)
|
||||
stw r3, THR3(\thread)
|
||||
stw r4, THR4(\thread)
|
||||
stw r5, THR5(\thread)
|
||||
stw r6, THR6(\thread)
|
||||
stw r8, THR8(\thread)
|
||||
stw r9, THR9(\thread)
|
||||
mflr r0
|
||||
stw r0, THLR(\thread)
|
||||
mfctr r0
|
||||
stw r0, THCTR(\thread)
|
||||
.endm
|
||||
|
||||
.macro restore_regs_thread thread
|
||||
lwz r0, THLR(\thread)
|
||||
mtlr r0
|
||||
lwz r0, THCTR(\thread)
|
||||
mtctr r0
|
||||
lwz r0, THR0(\thread)
|
||||
lwz r3, THR3(\thread)
|
||||
lwz r4, THR4(\thread)
|
||||
lwz r5, THR5(\thread)
|
||||
lwz r6, THR6(\thread)
|
||||
lwz r8, THR8(\thread)
|
||||
lwz r9, THR9(\thread)
|
||||
.endm
|
||||
|
||||
hash_page_dsi:
|
||||
save_regs_thread r10
|
||||
mfdsisr r3
|
||||
mfdar r4
|
||||
mfsrr0 r5
|
||||
mfsrr1 r9
|
||||
rlwinm r3, r3, 32 - 15, _PAGE_RW /* DSISR_STORE -> _PAGE_RW */
|
||||
bl hash_page
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
restore_regs_thread r10
|
||||
b .Lhash_page_dsi_cont
|
||||
|
||||
hash_page_isi:
|
||||
mr r11, r10
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
save_regs_thread r10
|
||||
li r3, 0
|
||||
lwz r4, SRR0(r10)
|
||||
lwz r9, SRR1(r10)
|
||||
bl hash_page
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
restore_regs_thread r10
|
||||
mr r10, r11
|
||||
b .Lhash_page_isi_cont
|
||||
|
||||
.globl fast_hash_page_return
|
||||
fast_hash_page_return:
|
||||
andis. r10, r9, SRR1_ISI_NOPT@h /* Set on ISI, cleared on DSI */
|
||||
mfspr r10, SPRN_SPRG_THREAD
|
||||
restore_regs_thread r10
|
||||
bne 1f
|
||||
|
||||
/* DSI */
|
||||
mtcr r11
|
||||
lwz r11, THR11(r10)
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
SYNC
|
||||
RFI
|
||||
|
||||
1: /* ISI */
|
||||
mtcr r11
|
||||
mfspr r11, SPRN_SPRG_SCRATCH1
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
SYNC
|
||||
RFI
|
||||
|
||||
stack_overflow:
|
||||
vmap_stack_overflow_exception
|
||||
#endif
|
||||
|
||||
AltiVecUnavailable:
|
||||
EXCEPTION_PROLOG
|
||||
|
@ -64,11 +64,25 @@
|
||||
.endm
|
||||
|
||||
.macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
|
||||
#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
mtcr r10
|
||||
FTR_SECTION_ELSE
|
||||
stw r10, _CCR(r11)
|
||||
ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#else
|
||||
stw r10,_CCR(r11) /* save registers */
|
||||
#endif
|
||||
mfspr r10, SPRN_SPRG_SCRATCH0
|
||||
stw r12,GPR12(r11)
|
||||
stw r9,GPR9(r11)
|
||||
mfspr r10,SPRN_SPRG_SCRATCH0
|
||||
stw r10,GPR10(r11)
|
||||
#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
mfcr r10
|
||||
stw r10, _CCR(r11)
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#endif
|
||||
mfspr r12,SPRN_SPRG_SCRATCH1
|
||||
stw r12,GPR11(r11)
|
||||
mflr r10
|
||||
@ -83,6 +97,11 @@
|
||||
stw r10, _DSISR(r11)
|
||||
.endif
|
||||
lwz r9, SRR1(r12)
|
||||
#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
|
||||
BEGIN_MMU_FTR_SECTION
|
||||
andi. r10, r9, MSR_PR
|
||||
END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
|
||||
#endif
|
||||
lwz r12, SRR0(r12)
|
||||
#else
|
||||
mfspr r12,SPRN_SRR0
|
||||
|
@ -256,7 +256,7 @@ InstructionTLBMiss:
|
||||
* set. All other Linux PTE bits control the behavior
|
||||
* of the MMU.
|
||||
*/
|
||||
rlwimi r10, r10, 0, 0x0f00 /* Clear bits 20-23 */
|
||||
rlwinm r10, r10, 0, ~0x0f00 /* Clear bits 20-23 */
|
||||
rlwimi r10, r10, 4, 0x0400 /* Copy _PAGE_EXEC into bit 21 */
|
||||
ori r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
|
||||
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
|
||||
|
@ -331,11 +331,13 @@ int hw_breakpoint_handler(struct die_args *args)
|
||||
}
|
||||
|
||||
info->type &= ~HW_BRK_TYPE_EXTRANEOUS_IRQ;
|
||||
if (!dar_within_range(regs->dar, info))
|
||||
info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PPC_8xx) && !stepping_handler(regs, bp, info))
|
||||
goto out;
|
||||
if (IS_ENABLED(CONFIG_PPC_8xx)) {
|
||||
if (!dar_within_range(regs->dar, info))
|
||||
info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ;
|
||||
} else {
|
||||
if (!stepping_handler(regs, bp, info))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* As a policy, the callback is invoked in a 'trigger-after-execute'
|
||||
|
@ -166,7 +166,11 @@ BEGIN_FTR_SECTION
|
||||
mfspr r9,SPRN_HID0
|
||||
andis. r9,r9,HID0_NAP@h
|
||||
beq 1f
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
addis r9, r11, nap_save_msscr0@ha
|
||||
#else
|
||||
addis r9,r11,(nap_save_msscr0-KERNELBASE)@ha
|
||||
#endif
|
||||
lwz r9,nap_save_msscr0@l(r9)
|
||||
mtspr SPRN_MSSCR0, r9
|
||||
sync
|
||||
@ -174,7 +178,11 @@ BEGIN_FTR_SECTION
|
||||
1:
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
|
||||
BEGIN_FTR_SECTION
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
addis r9, r11, nap_save_hid1@ha
|
||||
#else
|
||||
addis r9,r11,(nap_save_hid1-KERNELBASE)@ha
|
||||
#endif
|
||||
lwz r9,nap_save_hid1@l(r9)
|
||||
mtspr SPRN_HID1, r9
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
|
||||
|
@ -200,14 +200,27 @@ unsigned long get_tm_stackpointer(struct task_struct *tsk)
|
||||
* normal/non-checkpointed stack pointer.
|
||||
*/
|
||||
|
||||
unsigned long ret = tsk->thread.regs->gpr[1];
|
||||
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
BUG_ON(tsk != current);
|
||||
|
||||
if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
|
||||
preempt_disable();
|
||||
tm_reclaim_current(TM_CAUSE_SIGNAL);
|
||||
if (MSR_TM_TRANSACTIONAL(tsk->thread.regs->msr))
|
||||
return tsk->thread.ckpt_regs.gpr[1];
|
||||
ret = tsk->thread.ckpt_regs.gpr[1];
|
||||
|
||||
/*
|
||||
* If we treclaim, we must clear the current thread's TM bits
|
||||
* before re-enabling preemption. Otherwise we might be
|
||||
* preempted and have the live MSR[TS] changed behind our back
|
||||
* (tm_recheckpoint_new_task() would recheckpoint). Besides, we
|
||||
* enter the signal handler in non-transactional state.
|
||||
*/
|
||||
tsk->thread.regs->msr &= ~MSR_TS_MASK;
|
||||
preempt_enable();
|
||||
}
|
||||
#endif
|
||||
return tsk->thread.regs->gpr[1];
|
||||
return ret;
|
||||
}
|
||||
|
@ -489,19 +489,11 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
|
||||
*/
|
||||
static int save_tm_user_regs(struct pt_regs *regs,
|
||||
struct mcontext __user *frame,
|
||||
struct mcontext __user *tm_frame, int sigret)
|
||||
struct mcontext __user *tm_frame, int sigret,
|
||||
unsigned long msr)
|
||||
{
|
||||
unsigned long msr = regs->msr;
|
||||
|
||||
WARN_ON(tm_suspend_disabled);
|
||||
|
||||
/* Remove TM bits from thread's MSR. The MSR in the sigcontext
|
||||
* just indicates to userland that we were doing a transaction, but we
|
||||
* don't want to return in transactional state. This also ensures
|
||||
* that flush_fp_to_thread won't set TIF_RESTORE_TM again.
|
||||
*/
|
||||
regs->msr &= ~MSR_TS_MASK;
|
||||
|
||||
/* Save both sets of general registers */
|
||||
if (save_general_regs(¤t->thread.ckpt_regs, frame)
|
||||
|| save_general_regs(regs, tm_frame))
|
||||
@ -912,6 +904,10 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
int sigret;
|
||||
unsigned long tramp;
|
||||
struct pt_regs *regs = tsk->thread.regs;
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
/* Save the thread's msr before get_tm_stackpointer() changes it */
|
||||
unsigned long msr = regs->msr;
|
||||
#endif
|
||||
|
||||
BUG_ON(tsk != current);
|
||||
|
||||
@ -944,13 +940,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
tm_frame = &rt_sf->uc_transact.uc_mcontext;
|
||||
if (MSR_TM_ACTIVE(regs->msr)) {
|
||||
if (MSR_TM_ACTIVE(msr)) {
|
||||
if (__put_user((unsigned long)&rt_sf->uc_transact,
|
||||
&rt_sf->uc.uc_link) ||
|
||||
__put_user((unsigned long)tm_frame,
|
||||
&rt_sf->uc_transact.uc_regs))
|
||||
goto badframe;
|
||||
if (save_tm_user_regs(regs, frame, tm_frame, sigret))
|
||||
if (save_tm_user_regs(regs, frame, tm_frame, sigret, msr))
|
||||
goto badframe;
|
||||
}
|
||||
else
|
||||
@ -1369,6 +1365,10 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
int sigret;
|
||||
unsigned long tramp;
|
||||
struct pt_regs *regs = tsk->thread.regs;
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
/* Save the thread's msr before get_tm_stackpointer() changes it */
|
||||
unsigned long msr = regs->msr;
|
||||
#endif
|
||||
|
||||
BUG_ON(tsk != current);
|
||||
|
||||
@ -1402,9 +1402,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
tm_mctx = &frame->mctx_transact;
|
||||
if (MSR_TM_ACTIVE(regs->msr)) {
|
||||
if (MSR_TM_ACTIVE(msr)) {
|
||||
if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
|
||||
sigret))
|
||||
sigret, msr))
|
||||
goto badframe;
|
||||
}
|
||||
else
|
||||
|
@ -192,7 +192,8 @@ static long setup_sigcontext(struct sigcontext __user *sc,
|
||||
static long setup_tm_sigcontexts(struct sigcontext __user *sc,
|
||||
struct sigcontext __user *tm_sc,
|
||||
struct task_struct *tsk,
|
||||
int signr, sigset_t *set, unsigned long handler)
|
||||
int signr, sigset_t *set, unsigned long handler,
|
||||
unsigned long msr)
|
||||
{
|
||||
/* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
|
||||
* process never used altivec yet (MSR_VEC is zero in pt_regs of
|
||||
@ -207,12 +208,11 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
|
||||
elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
|
||||
#endif
|
||||
struct pt_regs *regs = tsk->thread.regs;
|
||||
unsigned long msr = tsk->thread.regs->msr;
|
||||
long err = 0;
|
||||
|
||||
BUG_ON(tsk != current);
|
||||
|
||||
BUG_ON(!MSR_TM_ACTIVE(regs->msr));
|
||||
BUG_ON(!MSR_TM_ACTIVE(msr));
|
||||
|
||||
WARN_ON(tm_suspend_disabled);
|
||||
|
||||
@ -222,13 +222,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
|
||||
*/
|
||||
msr |= tsk->thread.ckpt_regs.msr & (MSR_FP | MSR_VEC | MSR_VSX);
|
||||
|
||||
/* Remove TM bits from thread's MSR. The MSR in the sigcontext
|
||||
* just indicates to userland that we were doing a transaction, but we
|
||||
* don't want to return in transactional state. This also ensures
|
||||
* that flush_fp_to_thread won't set TIF_RESTORE_TM again.
|
||||
*/
|
||||
regs->msr &= ~MSR_TS_MASK;
|
||||
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
err |= __put_user(v_regs, &sc->v_regs);
|
||||
err |= __put_user(tm_v_regs, &tm_sc->v_regs);
|
||||
@ -824,6 +817,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
|
||||
unsigned long newsp = 0;
|
||||
long err = 0;
|
||||
struct pt_regs *regs = tsk->thread.regs;
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
/* Save the thread's msr before get_tm_stackpointer() changes it */
|
||||
unsigned long msr = regs->msr;
|
||||
#endif
|
||||
|
||||
BUG_ON(tsk != current);
|
||||
|
||||
@ -841,7 +838,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
if (MSR_TM_ACTIVE(regs->msr)) {
|
||||
if (MSR_TM_ACTIVE(msr)) {
|
||||
/* The ucontext_t passed to userland points to the second
|
||||
* ucontext_t (for transactional state) with its uc_link ptr.
|
||||
*/
|
||||
@ -849,7 +846,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
|
||||
err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
|
||||
&frame->uc_transact.uc_mcontext,
|
||||
tsk, ksig->sig, NULL,
|
||||
(unsigned long)ksig->ka.sa.sa_handler);
|
||||
(unsigned long)ksig->ka.sa.sa_handler,
|
||||
msr);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
@ -303,6 +303,12 @@ SECTIONS
|
||||
*(.branch_lt)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_INFO_BTF
|
||||
.BTF : AT(ADDR(.BTF) - LOAD_OFFSET) {
|
||||
*(.BTF)
|
||||
}
|
||||
#endif
|
||||
|
||||
.opd : AT(ADDR(.opd) - LOAD_OFFSET) {
|
||||
__start_opd = .;
|
||||
KEEP(*(.opd))
|
||||
|
@ -25,12 +25,6 @@
|
||||
#include <asm/feature-fixups.h>
|
||||
#include <asm/code-patching-asm.h>
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
#define ADDR_OFFSET 0
|
||||
#else
|
||||
#define ADDR_OFFSET PAGE_OFFSET
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.section .bss
|
||||
.align 2
|
||||
@ -53,8 +47,8 @@ mmu_hash_lock:
|
||||
.text
|
||||
_GLOBAL(hash_page)
|
||||
#ifdef CONFIG_SMP
|
||||
lis r8, (mmu_hash_lock - ADDR_OFFSET)@h
|
||||
ori r8, r8, (mmu_hash_lock - ADDR_OFFSET)@l
|
||||
lis r8, (mmu_hash_lock - PAGE_OFFSET)@h
|
||||
ori r8, r8, (mmu_hash_lock - PAGE_OFFSET)@l
|
||||
lis r0,0x0fff
|
||||
b 10f
|
||||
11: lwz r6,0(r8)
|
||||
@ -72,12 +66,9 @@ _GLOBAL(hash_page)
|
||||
cmplw 0,r4,r0
|
||||
ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
|
||||
mfspr r5, SPRN_SPRG_PGDIR /* phys page-table root */
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
tovirt(r5, r5)
|
||||
#endif
|
||||
blt+ 112f /* assume user more likely */
|
||||
lis r5, (swapper_pg_dir - ADDR_OFFSET)@ha /* if kernel address, use */
|
||||
addi r5 ,r5 ,(swapper_pg_dir - ADDR_OFFSET)@l /* kernel page table */
|
||||
lis r5, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||
addi r5 ,r5 ,(swapper_pg_dir - PAGE_OFFSET)@l /* kernel page table */
|
||||
rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */
|
||||
112:
|
||||
#ifndef CONFIG_PTE_64BIT
|
||||
@ -89,9 +80,6 @@ _GLOBAL(hash_page)
|
||||
lwzx r8,r8,r5 /* Get L1 entry */
|
||||
rlwinm. r8,r8,0,0,20 /* extract pt base address */
|
||||
#endif
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
tovirt(r8, r8)
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
beq- hash_page_out /* return if no mapping */
|
||||
#else
|
||||
@ -143,30 +131,36 @@ retry:
|
||||
bne- retry /* retry if someone got there first */
|
||||
|
||||
mfsrin r3,r4 /* get segment reg for segment */
|
||||
#ifndef CONFIG_VMAP_STACK
|
||||
mfctr r0
|
||||
stw r0,_CTR(r11)
|
||||
#endif
|
||||
bl create_hpte /* add the hash table entry */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
eieio
|
||||
lis r8, (mmu_hash_lock - ADDR_OFFSET)@ha
|
||||
lis r8, (mmu_hash_lock - PAGE_OFFSET)@ha
|
||||
li r0,0
|
||||
stw r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
|
||||
stw r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
b fast_hash_page_return
|
||||
#else
|
||||
/* Return from the exception */
|
||||
lwz r5,_CTR(r11)
|
||||
mtctr r5
|
||||
lwz r0,GPR0(r11)
|
||||
lwz r8,GPR8(r11)
|
||||
b fast_exception_return
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
hash_page_out:
|
||||
eieio
|
||||
lis r8, (mmu_hash_lock - ADDR_OFFSET)@ha
|
||||
lis r8, (mmu_hash_lock - PAGE_OFFSET)@ha
|
||||
li r0,0
|
||||
stw r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
|
||||
stw r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
|
||||
blr
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
@ -341,7 +335,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
|
||||
patch_site 1f, patch__hash_page_A1
|
||||
patch_site 2f, patch__hash_page_A2
|
||||
/* Get the address of the primary PTE group in the hash table (r3) */
|
||||
0: lis r0, (Hash_base - ADDR_OFFSET)@h /* base address of hash table */
|
||||
0: lis r0, (Hash_base - PAGE_OFFSET)@h /* base address of hash table */
|
||||
1: rlwimi r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
|
||||
2: rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
|
||||
xor r3,r3,r0 /* make primary hash */
|
||||
@ -355,10 +349,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
|
||||
beq+ 10f /* no PTE: go look for an empty slot */
|
||||
tlbie r4
|
||||
|
||||
lis r4, (htab_hash_searches - ADDR_OFFSET)@ha
|
||||
lwz r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
|
||||
lis r4, (htab_hash_searches - PAGE_OFFSET)@ha
|
||||
lwz r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
|
||||
addi r6,r6,1 /* count how many searches we do */
|
||||
stw r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
|
||||
stw r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
|
||||
|
||||
/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
|
||||
mtctr r0
|
||||
@ -390,10 +384,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
|
||||
beq+ found_empty
|
||||
|
||||
/* update counter of times that the primary PTEG is full */
|
||||
lis r4, (primary_pteg_full - ADDR_OFFSET)@ha
|
||||
lwz r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
|
||||
lis r4, (primary_pteg_full - PAGE_OFFSET)@ha
|
||||
lwz r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
|
||||
addi r6,r6,1
|
||||
stw r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
|
||||
stw r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
|
||||
|
||||
patch_site 0f, patch__hash_page_C
|
||||
/* Search the secondary PTEG for an empty slot */
|
||||
@ -427,8 +421,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
|
||||
* lockup here but that shouldn't happen
|
||||
*/
|
||||
|
||||
1: lis r4, (next_slot - ADDR_OFFSET)@ha /* get next evict slot */
|
||||
lwz r6, (next_slot - ADDR_OFFSET)@l(r4)
|
||||
1: lis r4, (next_slot - PAGE_OFFSET)@ha /* get next evict slot */
|
||||
lwz r6, (next_slot - PAGE_OFFSET)@l(r4)
|
||||
addi r6,r6,HPTE_SIZE /* search for candidate */
|
||||
andi. r6,r6,7*HPTE_SIZE
|
||||
stw r6,next_slot@l(r4)
|
||||
|
@ -413,7 +413,7 @@ void __init MMU_init_hw(void)
|
||||
void __init MMU_init_hw_patch(void)
|
||||
{
|
||||
unsigned int hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
|
||||
unsigned int hash;
|
||||
unsigned int hash = (unsigned int)Hash - PAGE_OFFSET;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("hash:patch", 0x345);
|
||||
@ -425,11 +425,6 @@ void __init MMU_init_hw_patch(void)
|
||||
/*
|
||||
* Patch up the instructions in hashtable.S:create_hpte
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_VMAP_STACK))
|
||||
hash = (unsigned int)Hash;
|
||||
else
|
||||
hash = (unsigned int)Hash - PAGE_OFFSET;
|
||||
|
||||
modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
|
||||
modify_instruction_site(&patch__hash_page_A1, 0x7c0, hash_mb << 6);
|
||||
modify_instruction_site(&patch__hash_page_A2, 0x7c0, hash_mb2 << 6);
|
||||
@ -439,8 +434,7 @@ void __init MMU_init_hw_patch(void)
|
||||
/*
|
||||
* Patch up the instructions in hashtable.S:flush_hash_page
|
||||
*/
|
||||
modify_instruction_site(&patch__flush_hash_A0, 0xffff,
|
||||
((unsigned int)Hash - PAGE_OFFSET) >> 16);
|
||||
modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
|
||||
modify_instruction_site(&patch__flush_hash_A1, 0x7c0, hash_mb << 6);
|
||||
modify_instruction_site(&patch__flush_hash_A2, 0x7c0, hash_mb2 << 6);
|
||||
modify_instruction_site(&patch__flush_hash_B, 0xffff, hmask);
|
||||
|
@ -53,20 +53,24 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
|
||||
if (pshift >= pdshift) {
|
||||
cachep = PGT_CACHE(PTE_T_ORDER);
|
||||
num_hugepd = 1 << (pshift - pdshift);
|
||||
new = NULL;
|
||||
} else if (IS_ENABLED(CONFIG_PPC_8xx)) {
|
||||
cachep = PGT_CACHE(PTE_INDEX_SIZE);
|
||||
cachep = NULL;
|
||||
num_hugepd = 1;
|
||||
new = pte_alloc_one(mm);
|
||||
} else {
|
||||
cachep = PGT_CACHE(pdshift - pshift);
|
||||
num_hugepd = 1;
|
||||
new = NULL;
|
||||
}
|
||||
|
||||
if (!cachep) {
|
||||
if (!cachep && !new) {
|
||||
WARN_ONCE(1, "No page table cache created for hugetlb tables");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
|
||||
if (cachep)
|
||||
new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
|
||||
|
||||
BUG_ON(pshift > HUGEPD_SHIFT_MASK);
|
||||
BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
|
||||
@ -97,7 +101,10 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
|
||||
if (i < num_hugepd) {
|
||||
for (i = i - 1 ; i >= 0; i--, hpdp--)
|
||||
*hpdp = __hugepd(0);
|
||||
kmem_cache_free(cachep, new);
|
||||
if (cachep)
|
||||
kmem_cache_free(cachep, new);
|
||||
else
|
||||
pte_free(mm, new);
|
||||
} else {
|
||||
kmemleak_ignore(new);
|
||||
}
|
||||
@ -324,8 +331,7 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
|
||||
if (shift >= pdshift)
|
||||
hugepd_free(tlb, hugepte);
|
||||
else if (IS_ENABLED(CONFIG_PPC_8xx))
|
||||
pgtable_free_tlb(tlb, hugepte,
|
||||
get_hugepd_cache_index(PTE_INDEX_SIZE));
|
||||
pgtable_free_tlb(tlb, hugepte, 0);
|
||||
else
|
||||
pgtable_free_tlb(tlb, hugepte,
|
||||
get_hugepd_cache_index(pdshift - shift));
|
||||
@ -639,12 +645,13 @@ static int __init hugetlbpage_init(void)
|
||||
* if we have pdshift and shift value same, we don't
|
||||
* use pgt cache for hugepd.
|
||||
*/
|
||||
if (pdshift > shift && IS_ENABLED(CONFIG_PPC_8xx))
|
||||
pgtable_cache_add(PTE_INDEX_SIZE);
|
||||
else if (pdshift > shift)
|
||||
pgtable_cache_add(pdshift - shift);
|
||||
else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) || IS_ENABLED(CONFIG_PPC_8xx))
|
||||
if (pdshift > shift) {
|
||||
if (!IS_ENABLED(CONFIG_PPC_8xx))
|
||||
pgtable_cache_add(pdshift - shift);
|
||||
} else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) ||
|
||||
IS_ENABLED(CONFIG_PPC_8xx)) {
|
||||
pgtable_cache_add(PTE_T_ORDER);
|
||||
}
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
@ -185,8 +185,7 @@ u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
|
||||
|
||||
static void __init kasan_early_hash_table(void)
|
||||
{
|
||||
unsigned int hash = IS_ENABLED(CONFIG_VMAP_STACK) ? (unsigned int)early_hash :
|
||||
__pa(early_hash);
|
||||
unsigned int hash = __pa(early_hash);
|
||||
|
||||
modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
|
||||
modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
|
||||
|
@ -367,7 +367,9 @@ static inline bool flush_coherent_icache(unsigned long addr)
|
||||
*/
|
||||
if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) {
|
||||
mb(); /* sync */
|
||||
allow_read_from_user((const void __user *)addr, L1_CACHE_BYTES);
|
||||
icbi((void *)addr);
|
||||
prevent_read_from_user((const void __user *)addr, L1_CACHE_BYTES);
|
||||
mb(); /* sync */
|
||||
isync();
|
||||
return true;
|
||||
|
@ -3435,6 +3435,11 @@ getstring(char *s, int size)
|
||||
int c;
|
||||
|
||||
c = skipbl();
|
||||
if (c == '\n') {
|
||||
*s = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if( size > 1 ){
|
||||
*s++ = c;
|
||||
|
Loading…
x
Reference in New Issue
Block a user