mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-26 00:21:17 +00:00
powerpc fixes for 5.15 #2
Fix crashes when scv (System Call Vectored) is used to make a syscall when a transaction is active, on Power9 or later. Fix bad interactions between rfscv (Return-from scv) and Power9 fake-suspend mode. Fix crashes when handling machine checks in LPARs using the Hash MMU. Partly revert a recent change to our XICS interrupt controller code, which broke the recently added Microwatt support. Thanks to: Cédric Le Goater, Eirik Fuller, Ganesh Goudar, Gustavo Romero, Joel Stanley, Nicholas Piggin. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmFHDfsTHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgNlAD/oC/14jV2fCv54vH5Al1XAz2WuPhhEu UsN+MLlx7JshXfLeGzzEogvvakfLFuVkpIxsv+g8a9H6jejjCj/A4wjUy34Im0hS nhsMsa1vZPZY/Vz9v3WzdYmqjHVZDKo6ZdUmn0z4OjPnv7wQaEEbaXmoe0+CaXXQ jIY2TjVQxbgXeUI1QcPUWh36hiSaYn4O8fAD4VdjxdStl2z6q8zbo/5nzQ8dkBpP lldC0T/HRCKLe1ODUExFfbBFqFuLVdbALq0RIuh0GXd+dAqpK1iOkNsxUWChU6Q7 gu0PrmhRydX3bmL9jmOsZfUk/hIR0fEgwSGITQAb8v0LCvZI0JRn+yvkl7uVZ9Ce OWY7B8HZQldvoQqA4/f7YCpAIS2ag7ugDrcAfuDVkDl2o/qJHoTi58IU24wI6+LL lwJZjNJoxZ8n1tl1l+gtCNp4E4YYOfuKZi0zH0oJoLiSWeK6PYOvwEGuEC2iQ9cJ BEdyYVXqSBuc2anCQ4k+y8gu/zJwP1MCpDNMPMU4P/JcaG9lnrLUhvctf4GKtOSy UiktHSTL52J5ldMxSMicpw9qCVgePsQX78Sk3UTHRilRmix6TtWOWYslm4mL+zeD u3wpnK+NKkju72LRS/AB1U6cWvModW+WBANPws9j6caoOorh397xsDGEYiKWvp0Z xSG/dzXzi2oscQ== =yC9U -----END PGP SIGNATURE----- Merge tag 'powerpc-5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc fixes from Michael Ellerman: - Fix crashes when scv (System Call Vectored) is used to make a syscall when a transaction is active, on Power9 or later. - Fix bad interactions between rfscv (Return-from scv) and Power9 fake-suspend mode. - Fix crashes when handling machine checks in LPARs using the Hash MMU. - Partly revert a recent change to our XICS interrupt controller code, which broke the recently added Microwatt support. Thanks to Cédric Le Goater, Eirik Fuller, Ganesh Goudar, Gustavo Romero, Joel Stanley, Nicholas Piggin. * tag 'powerpc-5.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/xics: Set the IRQ chip data for the ICS native backend powerpc/mce: Fix access error in mce handler KVM: PPC: Book3S HV: Tolerate treclaim. in fake-suspend mode changing registers powerpc/64s: system call rfscv workaround for TM bugs selftests/powerpc: Add scv versions of the basic TM syscall tests powerpc/64s: system call scv tabort fix for corrupt irq soft-mask state
This commit is contained in:
commit
62453a460a
7 changed files with 159 additions and 55 deletions
|
@ -18,6 +18,7 @@
|
||||||
#include <asm/switch_to.h>
|
#include <asm/switch_to.h>
|
||||||
#include <asm/syscall.h>
|
#include <asm/syscall.h>
|
||||||
#include <asm/time.h>
|
#include <asm/time.h>
|
||||||
|
#include <asm/tm.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
|
||||||
#if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32)
|
#if defined(CONFIG_PPC_ADV_DEBUG_REGS) && defined(CONFIG_PPC32)
|
||||||
|
@ -136,6 +137,48 @@ notrace long system_call_exception(long r3, long r4, long r5,
|
||||||
*/
|
*/
|
||||||
irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
|
irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If system call is called with TM active, set _TIF_RESTOREALL to
|
||||||
|
* prevent RFSCV being used to return to userspace, because POWER9
|
||||||
|
* TM implementation has problems with this instruction returning to
|
||||||
|
* transactional state. Final register values are not relevant because
|
||||||
|
* the transaction will be aborted upon return anyway. Or in the case
|
||||||
|
* of unsupported_scv SIGILL fault, the return state does not much
|
||||||
|
* matter because it's an edge case.
|
||||||
|
*/
|
||||||
|
if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
|
||||||
|
unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
|
||||||
|
current_thread_info()->flags |= _TIF_RESTOREALL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the system call was made with a transaction active, doom it and
|
||||||
|
* return without performing the system call. Unless it was an
|
||||||
|
* unsupported scv vector, in which case it's treated like an illegal
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
|
if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) &&
|
||||||
|
!trap_is_unsupported_scv(regs)) {
|
||||||
|
/* Enable TM in the kernel, and disable EE (for scv) */
|
||||||
|
hard_irq_disable();
|
||||||
|
mtmsr(mfmsr() | MSR_TM);
|
||||||
|
|
||||||
|
/* tabort, this dooms the transaction, nothing else */
|
||||||
|
asm volatile(".long 0x7c00071d | ((%0) << 16)"
|
||||||
|
:: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Userspace will never see the return value. Execution will
|
||||||
|
* resume after the tbegin. of the aborted transaction with the
|
||||||
|
* checkpointed register state. A context switch could occur
|
||||||
|
* or signal delivered to the process before resuming the
|
||||||
|
* doomed transaction context, but that should all be handled
|
||||||
|
* as expected.
|
||||||
|
*/
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
#endif // CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) {
|
if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) {
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
#include <asm/ppc_asm.h>
|
#include <asm/ppc_asm.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/tm.h>
|
|
||||||
|
|
||||||
.section ".toc","aw"
|
.section ".toc","aw"
|
||||||
SYS_CALL_TABLE:
|
SYS_CALL_TABLE:
|
||||||
|
@ -55,12 +54,6 @@ COMPAT_SYS_CALL_TABLE:
|
||||||
.globl system_call_vectored_\name
|
.globl system_call_vectored_\name
|
||||||
system_call_vectored_\name:
|
system_call_vectored_\name:
|
||||||
_ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
|
_ASM_NOKPROBE_SYMBOL(system_call_vectored_\name)
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
||||||
BEGIN_FTR_SECTION
|
|
||||||
extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
|
|
||||||
bne tabort_syscall
|
|
||||||
END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|
||||||
#endif
|
|
||||||
SCV_INTERRUPT_TO_KERNEL
|
SCV_INTERRUPT_TO_KERNEL
|
||||||
mr r10,r1
|
mr r10,r1
|
||||||
ld r1,PACAKSAVE(r13)
|
ld r1,PACAKSAVE(r13)
|
||||||
|
@ -247,12 +240,6 @@ _ASM_NOKPROBE_SYMBOL(system_call_common_real)
|
||||||
.globl system_call_common
|
.globl system_call_common
|
||||||
system_call_common:
|
system_call_common:
|
||||||
_ASM_NOKPROBE_SYMBOL(system_call_common)
|
_ASM_NOKPROBE_SYMBOL(system_call_common)
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
||||||
BEGIN_FTR_SECTION
|
|
||||||
extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
|
|
||||||
bne tabort_syscall
|
|
||||||
END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|
||||||
#endif
|
|
||||||
mr r10,r1
|
mr r10,r1
|
||||||
ld r1,PACAKSAVE(r13)
|
ld r1,PACAKSAVE(r13)
|
||||||
std r10,0(r1)
|
std r10,0(r1)
|
||||||
|
@ -425,34 +412,6 @@ SOFT_MASK_TABLE(.Lsyscall_rst_start, 1b)
|
||||||
RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart)
|
RESTART_TABLE(.Lsyscall_rst_start, .Lsyscall_rst_end, syscall_restart)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
||||||
tabort_syscall:
|
|
||||||
_ASM_NOKPROBE_SYMBOL(tabort_syscall)
|
|
||||||
/* Firstly we need to enable TM in the kernel */
|
|
||||||
mfmsr r10
|
|
||||||
li r9, 1
|
|
||||||
rldimi r10, r9, MSR_TM_LG, 63-MSR_TM_LG
|
|
||||||
mtmsrd r10, 0
|
|
||||||
|
|
||||||
/* tabort, this dooms the transaction, nothing else */
|
|
||||||
li r9, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
|
|
||||||
TABORT(R9)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return directly to userspace. We have corrupted user register state,
|
|
||||||
* but userspace will never see that register state. Execution will
|
|
||||||
* resume after the tbegin of the aborted transaction with the
|
|
||||||
* checkpointed register state.
|
|
||||||
*/
|
|
||||||
li r9, MSR_RI
|
|
||||||
andc r10, r10, r9
|
|
||||||
mtmsrd r10, 1
|
|
||||||
mtspr SPRN_SRR0, r11
|
|
||||||
mtspr SPRN_SRR1, r12
|
|
||||||
RFI_TO_USER
|
|
||||||
b . /* prevent speculative execution */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
|
* If MSR EE/RI was never enabled, IRQs not reconciled, NVGPRs not
|
||||||
* touched, no exit work created, then this can be used.
|
* touched, no exit work created, then this can be used.
|
||||||
|
|
|
@ -249,6 +249,7 @@ void machine_check_queue_event(void)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
struct machine_check_event evt;
|
struct machine_check_event evt;
|
||||||
|
unsigned long msr;
|
||||||
|
|
||||||
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
|
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
|
||||||
return;
|
return;
|
||||||
|
@ -262,8 +263,20 @@ void machine_check_queue_event(void)
|
||||||
memcpy(&local_paca->mce_info->mce_event_queue[index],
|
memcpy(&local_paca->mce_info->mce_event_queue[index],
|
||||||
&evt, sizeof(evt));
|
&evt, sizeof(evt));
|
||||||
|
|
||||||
/* Queue irq work to process this event later. */
|
/*
|
||||||
irq_work_queue(&mce_event_process_work);
|
* Queue irq work to process this event later. Before
|
||||||
|
* queuing the work enable translation for non radix LPAR,
|
||||||
|
* as irq_work_queue may try to access memory outside RMO
|
||||||
|
* region.
|
||||||
|
*/
|
||||||
|
if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) {
|
||||||
|
msr = mfmsr();
|
||||||
|
mtmsr(msr | MSR_IR | MSR_DR);
|
||||||
|
irq_work_queue(&mce_event_process_work);
|
||||||
|
mtmsr(msr);
|
||||||
|
} else {
|
||||||
|
irq_work_queue(&mce_event_process_work);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mce_common_process_ue(struct pt_regs *regs,
|
void mce_common_process_ue(struct pt_regs *regs,
|
||||||
|
|
|
@ -2536,7 +2536,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
|
||||||
/* The following code handles the fake_suspend = 1 case */
|
/* The following code handles the fake_suspend = 1 case */
|
||||||
mflr r0
|
mflr r0
|
||||||
std r0, PPC_LR_STKOFF(r1)
|
std r0, PPC_LR_STKOFF(r1)
|
||||||
stdu r1, -PPC_MIN_STKFRM(r1)
|
stdu r1, -TM_FRAME_SIZE(r1)
|
||||||
|
|
||||||
/* Turn on TM. */
|
/* Turn on TM. */
|
||||||
mfmsr r8
|
mfmsr r8
|
||||||
|
@ -2551,10 +2551,42 @@ BEGIN_FTR_SECTION
|
||||||
END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
|
END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's possible that treclaim. may modify registers, if we have lost
|
||||||
|
* track of fake-suspend state in the guest due to it using rfscv.
|
||||||
|
* Save and restore registers in case this occurs.
|
||||||
|
*/
|
||||||
|
mfspr r3, SPRN_DSCR
|
||||||
|
mfspr r4, SPRN_XER
|
||||||
|
mfspr r5, SPRN_AMR
|
||||||
|
/* SPRN_TAR would need to be saved here if the kernel ever used it */
|
||||||
|
mfcr r12
|
||||||
|
SAVE_NVGPRS(r1)
|
||||||
|
SAVE_GPR(2, r1)
|
||||||
|
SAVE_GPR(3, r1)
|
||||||
|
SAVE_GPR(4, r1)
|
||||||
|
SAVE_GPR(5, r1)
|
||||||
|
stw r12, 8(r1)
|
||||||
|
std r1, HSTATE_HOST_R1(r13)
|
||||||
|
|
||||||
/* We have to treclaim here because that's the only way to do S->N */
|
/* We have to treclaim here because that's the only way to do S->N */
|
||||||
li r3, TM_CAUSE_KVM_RESCHED
|
li r3, TM_CAUSE_KVM_RESCHED
|
||||||
TRECLAIM(R3)
|
TRECLAIM(R3)
|
||||||
|
|
||||||
|
GET_PACA(r13)
|
||||||
|
ld r1, HSTATE_HOST_R1(r13)
|
||||||
|
REST_GPR(2, r1)
|
||||||
|
REST_GPR(3, r1)
|
||||||
|
REST_GPR(4, r1)
|
||||||
|
REST_GPR(5, r1)
|
||||||
|
lwz r12, 8(r1)
|
||||||
|
REST_NVGPRS(r1)
|
||||||
|
mtspr SPRN_DSCR, r3
|
||||||
|
mtspr SPRN_XER, r4
|
||||||
|
mtspr SPRN_AMR, r5
|
||||||
|
mtcr r12
|
||||||
|
HMT_MEDIUM
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We were in fake suspend, so we are not going to save the
|
* We were in fake suspend, so we are not going to save the
|
||||||
* register state as the guest checkpointed state (since
|
* register state as the guest checkpointed state (since
|
||||||
|
@ -2582,7 +2614,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
|
||||||
std r5, VCPU_TFHAR(r9)
|
std r5, VCPU_TFHAR(r9)
|
||||||
std r6, VCPU_TFIAR(r9)
|
std r6, VCPU_TFIAR(r9)
|
||||||
|
|
||||||
addi r1, r1, PPC_MIN_STKFRM
|
addi r1, r1, TM_FRAME_SIZE
|
||||||
ld r0, PPC_LR_STKOFF(r1)
|
ld r0, PPC_LR_STKOFF(r1)
|
||||||
mtlr r0
|
mtlr r0
|
||||||
blr
|
blr
|
||||||
|
|
|
@ -348,9 +348,9 @@ static int xics_host_map(struct irq_domain *domain, unsigned int virq,
|
||||||
if (xics_ics->check(xics_ics, hwirq))
|
if (xics_ics->check(xics_ics, hwirq))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* No chip data for the XICS domain */
|
/* Let the ICS be the chip data for the XICS domain. For ICS native */
|
||||||
irq_domain_set_info(domain, virq, hwirq, xics_ics->chip,
|
irq_domain_set_info(domain, virq, hwirq, xics_ics->chip,
|
||||||
NULL, handle_fasteoi_irq, NULL, NULL);
|
xics_ics, handle_fasteoi_irq, NULL, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
#include <ppc-asm.h>
|
#include <basic_asm.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
@ -26,3 +26,38 @@ FUNC_START(getppid_tm_suspended)
|
||||||
1:
|
1:
|
||||||
li r3, -1
|
li r3, -1
|
||||||
blr
|
blr
|
||||||
|
|
||||||
|
|
||||||
|
.macro scv level
|
||||||
|
.long (0x44000001 | (\level) << 5)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
FUNC_START(getppid_scv_tm_active)
|
||||||
|
PUSH_BASIC_STACK(0)
|
||||||
|
tbegin.
|
||||||
|
beq 1f
|
||||||
|
li r0, __NR_getppid
|
||||||
|
scv 0
|
||||||
|
tend.
|
||||||
|
POP_BASIC_STACK(0)
|
||||||
|
blr
|
||||||
|
1:
|
||||||
|
li r3, -1
|
||||||
|
POP_BASIC_STACK(0)
|
||||||
|
blr
|
||||||
|
|
||||||
|
FUNC_START(getppid_scv_tm_suspended)
|
||||||
|
PUSH_BASIC_STACK(0)
|
||||||
|
tbegin.
|
||||||
|
beq 1f
|
||||||
|
li r0, __NR_getppid
|
||||||
|
tsuspend.
|
||||||
|
scv 0
|
||||||
|
tresume.
|
||||||
|
tend.
|
||||||
|
POP_BASIC_STACK(0)
|
||||||
|
blr
|
||||||
|
1:
|
||||||
|
li r3, -1
|
||||||
|
POP_BASIC_STACK(0)
|
||||||
|
blr
|
||||||
|
|
|
@ -19,23 +19,36 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "tm.h"
|
#include "tm.h"
|
||||||
|
|
||||||
|
#ifndef PPC_FEATURE2_SCV
|
||||||
|
#define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int getppid_tm_active(void);
|
extern int getppid_tm_active(void);
|
||||||
extern int getppid_tm_suspended(void);
|
extern int getppid_tm_suspended(void);
|
||||||
|
extern int getppid_scv_tm_active(void);
|
||||||
|
extern int getppid_scv_tm_suspended(void);
|
||||||
|
|
||||||
unsigned retries = 0;
|
unsigned retries = 0;
|
||||||
|
|
||||||
#define TEST_DURATION 10 /* seconds */
|
#define TEST_DURATION 10 /* seconds */
|
||||||
|
|
||||||
pid_t getppid_tm(bool suspend)
|
pid_t getppid_tm(bool scv, bool suspend)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
for (i = 0; i < TM_RETRIES; i++) {
|
for (i = 0; i < TM_RETRIES; i++) {
|
||||||
if (suspend)
|
if (suspend) {
|
||||||
pid = getppid_tm_suspended();
|
if (scv)
|
||||||
else
|
pid = getppid_scv_tm_suspended();
|
||||||
pid = getppid_tm_active();
|
else
|
||||||
|
pid = getppid_tm_suspended();
|
||||||
|
} else {
|
||||||
|
if (scv)
|
||||||
|
pid = getppid_scv_tm_active();
|
||||||
|
else
|
||||||
|
pid = getppid_tm_active();
|
||||||
|
}
|
||||||
|
|
||||||
if (pid >= 0)
|
if (pid >= 0)
|
||||||
return pid;
|
return pid;
|
||||||
|
@ -82,15 +95,24 @@ int tm_syscall(void)
|
||||||
* Test a syscall within a suspended transaction and verify
|
* Test a syscall within a suspended transaction and verify
|
||||||
* that it succeeds.
|
* that it succeeds.
|
||||||
*/
|
*/
|
||||||
FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */
|
FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test a syscall within an active transaction and verify that
|
* Test a syscall within an active transaction and verify that
|
||||||
* it fails with the correct failure code.
|
* it fails with the correct failure code.
|
||||||
*/
|
*/
|
||||||
FAIL_IF(getppid_tm(false) != -1); /* Should fail... */
|
FAIL_IF(getppid_tm(false, false) != -1); /* Should fail... */
|
||||||
FAIL_IF(!failure_is_persistent()); /* ...persistently... */
|
FAIL_IF(!failure_is_persistent()); /* ...persistently... */
|
||||||
FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
|
FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
|
||||||
|
|
||||||
|
/* Now do it all again with scv if it is available. */
|
||||||
|
if (have_hwcap2(PPC_FEATURE2_SCV)) {
|
||||||
|
FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */
|
||||||
|
FAIL_IF(getppid_tm(true, false) != -1); /* Should fail... */
|
||||||
|
FAIL_IF(!failure_is_persistent()); /* ...persistently... */
|
||||||
|
FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
|
||||||
|
}
|
||||||
|
|
||||||
gettimeofday(&now, 0);
|
gettimeofday(&now, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue