From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-11.3 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, NICE_REPLY_A,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51383C43461 for ; Thu, 17 Sep 2020 13:38:11 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 219782075E for ; Thu, 17 Sep 2020 13:38:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="VZwEte6m" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 219782075E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.ibm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4BsdMM39JNzDqJN for ; Thu, 17 Sep 2020 23:38:07 +1000 (AEST) Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=rcardoso@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=VZwEte6m; dkim-atps=neutral Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4Bsd5S4sz2zDqNX for ; Thu, 17 Sep 2020 23:26:04 +1000 (AEST) Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 08HD30Ac062591; Thu, 17 Sep 2020 09:25:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=subject : to : cc : references : from : message-id : date : mime-version : in-reply-to : content-type : content-transfer-encoding; s=pp1; bh=KJs+9AkV/Y/e9mnK0W4by+0XXHnVMfKuUiXVOO5ApH8=; b=VZwEte6mD5H1VucttDDz+RmXMsIQlEEyLGn3djkIoCfwIsnDlmP1i/10XXf0GLCq06yC nOi8efVUqyMIbApEIsjqKT/BYUZk7zhyg0Sn9IGqjLGaRb8/23wNaictxa/GneZiUKMO G0Ss8DOfX8rwMWvIP8Ko2pQMuOfJnt52K+jLm0Y1EDcEHWgksrErmhDZY9YY4WBtdWzQ KJAPvuUWwQgVpjSeq9kuojFfQLbc3mrYfwIONL4xT9XR/AJvd+46y7KTo1B4pVEnf9Xm oBYu0yqo34xbDpDq3j+O+H0yq+zze1Om0PziHCqZXlIEpjwYyVfbe78fdw+Ua3OIQtU4 mA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 33m7fbaru8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 17 Sep 2020 09:25:54 -0400 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.36/8.16.0.36) with SMTP id 08HD3tph067836; Thu, 17 Sep 2020 09:25:53 -0400 Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0a-001b2d01.pphosted.com with ESMTP id 33m7fbarth-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 17 Sep 2020 09:25:53 -0400 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.16.0.42/8.16.0.42) with SMTP id 08HDLljd006129; Thu, 17 Sep 2020 13:25:52 GMT Received: from b01cxnp22035.gho.pok.ibm.com (b01cxnp22035.gho.pok.ibm.com [9.57.198.25]) by ppma05wdc.us.ibm.com with ESMTP id 33k6q14efs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 17 Sep 2020 13:25:52 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 08HDPpNl49414478 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 17 Sep 2020 13:25:51 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BEECEAE062; Thu, 17 Sep 2020 13:25:51 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3D3FFAE05F; Thu, 17 Sep 2020 13:25:48 +0000 (GMT) Received: from localhost.localdomain (unknown [9.211.95.89]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTP; Thu, 17 Sep 2020 13:25:47 +0000 (GMT) Subject: Re: [PATCH v6 4/8] powerpc/watchpoint: Move DAWR detection logic outside of hw_breakpoint.c To: Ravi Bangoria , mpe@ellerman.id.au, christophe.leroy@c-s.fr References: <20200902042945.129369-1-ravi.bangoria@linux.ibm.com> <20200902042945.129369-5-ravi.bangoria@linux.ibm.com> From: Rogerio Alves Message-ID: <5684e581-ea19-979e-579b-7259dfe3c1f3@linux.ibm.com> Date: Thu, 17 Sep 2020 10:25:47 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <20200902042945.129369-5-ravi.bangoria@linux.ibm.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235, 18.0.687 definitions=2020-09-17_09:2020-09-16, 2020-09-17 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 lowpriorityscore=0 malwarescore=0 mlxscore=0 clxscore=1015 mlxlogscore=999 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 impostorscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2006250000 definitions=main-2009170098 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mikey@neuling.org, jniethe5@gmail.com, pedromfc@linux.ibm.com, linux-kernel@vger.kernel.org, paulus@samba.org, rogealve@linux.ibm.com, naveen.n.rao@linux.vnet.ibm.com, linuxppc-dev@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Sender: "Linuxppc-dev" On 9/2/20 1:29 AM, Ravi Bangoria wrote: > Power10 hw has multiple DAWRs but hw doesn't tell which DAWR caused > the exception. So we have a sw logic to detect that in hw_breakpoint.c. > But hw_breakpoint.c gets compiled only with CONFIG_HAVE_HW_BREAKPOINT=Y. > Move DAWR detection logic outside of hw_breakpoint.c so that it can be > reused when CONFIG_HAVE_HW_BREAKPOINT is not set. > > Signed-off-by: Ravi Bangoria Tested-by: Rogerio Alves > --- > arch/powerpc/include/asm/hw_breakpoint.h | 8 + > arch/powerpc/kernel/Makefile | 3 +- > arch/powerpc/kernel/hw_breakpoint.c | 159 +---------------- > .../kernel/hw_breakpoint_constraints.c | 162 ++++++++++++++++++ > 4 files changed, 174 insertions(+), 158 deletions(-) > create mode 100644 arch/powerpc/kernel/hw_breakpoint_constraints.c > > diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h > index 9b68eafebf43..81872c420476 100644 > --- a/arch/powerpc/include/asm/hw_breakpoint.h > +++ b/arch/powerpc/include/asm/hw_breakpoint.h > @@ -10,6 +10,7 @@ > #define _PPC_BOOK3S_64_HW_BREAKPOINT_H > > #include > +#include > > #ifdef __KERNEL__ > struct arch_hw_breakpoint { > @@ -52,6 +53,13 @@ static inline int nr_wp_slots(void) > return cpu_has_feature(CPU_FTR_DAWR1) ? 2 : 1; > } > > +bool wp_check_constraints(struct pt_regs *regs, struct ppc_inst instr, > + unsigned long ea, int type, int size, > + struct arch_hw_breakpoint *info); > + > +void wp_get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr, > + int *type, int *size, unsigned long *ea); > + > #ifdef CONFIG_HAVE_HW_BREAKPOINT > #include > #include > diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile > index cbf41fb4ee89..a5550c2b24c4 100644 > --- a/arch/powerpc/kernel/Makefile > +++ b/arch/powerpc/kernel/Makefile > @@ -45,7 +45,8 @@ obj-y := cputable.o syscalls.o \ > signal.o sysfs.o cacheinfo.o time.o \ > prom.o traps.o setup-common.o \ > udbg.o misc.o io.o misc_$(BITS).o \ > - of_platform.o prom_parse.o firmware.o > + of_platform.o prom_parse.o firmware.o \ > + hw_breakpoint_constraints.o > obj-y += ptrace/ > obj-$(CONFIG_PPC64) += setup_64.o \ > paca.o nvram_64.o note.o syscall_64.o > diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c > index f6b24838ca3c..f4e8f21046f5 100644 > --- a/arch/powerpc/kernel/hw_breakpoint.c > +++ b/arch/powerpc/kernel/hw_breakpoint.c > @@ -494,161 +494,6 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs) > } > } > > -static bool dar_in_user_range(unsigned long dar, struct arch_hw_breakpoint *info) > -{ > - return ((info->address <= dar) && (dar - info->address < info->len)); > -} > - > -static bool ea_user_range_overlaps(unsigned long ea, int size, > - struct arch_hw_breakpoint *info) > -{ > - return ((ea < info->address + info->len) && > - (ea + size > info->address)); > -} > - > -static bool dar_in_hw_range(unsigned long dar, struct arch_hw_breakpoint *info) > -{ > - unsigned long hw_start_addr, hw_end_addr; > - > - hw_start_addr = ALIGN_DOWN(info->address, HW_BREAKPOINT_SIZE); > - hw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE); > - > - return ((hw_start_addr <= dar) && (hw_end_addr > dar)); > -} > - > -static bool ea_hw_range_overlaps(unsigned long ea, int size, > - struct arch_hw_breakpoint *info) > -{ > - unsigned long hw_start_addr, hw_end_addr; > - unsigned long align_size = HW_BREAKPOINT_SIZE; > - > - /* > - * On p10 predecessors, quadword is handle differently then > - * other instructions. > - */ > - if (!cpu_has_feature(CPU_FTR_ARCH_31) && size == 16) > - align_size = HW_BREAKPOINT_SIZE_QUADWORD; > - > - hw_start_addr = ALIGN_DOWN(info->address, align_size); > - hw_end_addr = ALIGN(info->address + info->len, align_size); > - > - return ((ea < hw_end_addr) && (ea + size > hw_start_addr)); > -} > - > -/* > - * If hw has multiple DAWR registers, we also need to check all > - * dawrx constraint bits to confirm this is _really_ a valid event. > - * If type is UNKNOWN, but privilege level matches, consider it as > - * a positive match. > - */ > -static bool check_dawrx_constraints(struct pt_regs *regs, int type, > - struct arch_hw_breakpoint *info) > -{ > - if (OP_IS_LOAD(type) && !(info->type & HW_BRK_TYPE_READ)) > - return false; > - > - /* > - * The Cache Management instructions other than dcbz never > - * cause a match. i.e. if type is CACHEOP, the instruction > - * is dcbz, and dcbz is treated as Store. > - */ > - if ((OP_IS_STORE(type) || type == CACHEOP) && !(info->type & HW_BRK_TYPE_WRITE)) > - return false; > - > - if (is_kernel_addr(regs->nip) && !(info->type & HW_BRK_TYPE_KERNEL)) > - return false; > - > - if (user_mode(regs) && !(info->type & HW_BRK_TYPE_USER)) > - return false; > - > - return true; > -} > - > -/* > - * Return true if the event is valid wrt dawr configuration, > - * including extraneous exception. Otherwise return false. > - */ > -static bool check_constraints(struct pt_regs *regs, struct ppc_inst instr, > - unsigned long ea, int type, int size, > - struct arch_hw_breakpoint *info) > -{ > - bool in_user_range = dar_in_user_range(regs->dar, info); > - bool dawrx_constraints; > - > - /* > - * 8xx supports only one breakpoint and thus we can > - * unconditionally return true. > - */ > - if (IS_ENABLED(CONFIG_PPC_8xx)) { > - if (!in_user_range) > - info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ; > - return true; > - } > - > - if (unlikely(ppc_inst_equal(instr, ppc_inst(0)))) { > - if (cpu_has_feature(CPU_FTR_ARCH_31) && > - !dar_in_hw_range(regs->dar, info)) > - return false; > - > - return true; > - } > - > - dawrx_constraints = check_dawrx_constraints(regs, type, info); > - > - if (type == UNKNOWN) { > - if (cpu_has_feature(CPU_FTR_ARCH_31) && > - !dar_in_hw_range(regs->dar, info)) > - return false; > - > - return dawrx_constraints; > - } > - > - if (ea_user_range_overlaps(ea, size, info)) > - return dawrx_constraints; > - > - if (ea_hw_range_overlaps(ea, size, info)) { > - if (dawrx_constraints) { > - info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ; > - return true; > - } > - } > - return false; > -} > - > -static int cache_op_size(void) > -{ > -#ifdef __powerpc64__ > - return ppc64_caches.l1d.block_size; > -#else > - return L1_CACHE_BYTES; > -#endif > -} > - > -static void get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr, > - int *type, int *size, unsigned long *ea) > -{ > - struct instruction_op op; > - > - if (__get_user_instr_inatomic(*instr, (void __user *)regs->nip)) > - return; > - > - analyse_instr(&op, regs, *instr); > - *type = GETTYPE(op.type); > - *ea = op.ea; > -#ifdef __powerpc64__ > - if (!(regs->msr & MSR_64BIT)) > - *ea &= 0xffffffffUL; > -#endif > - > - *size = GETSIZE(op.type); > - if (*type == CACHEOP) { > - *size = cache_op_size(); > - *ea &= ~(*size - 1); > - } else if (*type == LOAD_VMX || *type == STORE_VMX) { > - *ea &= ~(*size - 1); > - } > -} > - > static bool is_larx_stcx_instr(int type) > { > return type == LARX || type == STCX; > @@ -732,7 +577,7 @@ int hw_breakpoint_handler(struct die_args *args) > rcu_read_lock(); > > if (!IS_ENABLED(CONFIG_PPC_8xx)) > - get_instr_detail(regs, &instr, &type, &size, &ea); > + wp_get_instr_detail(regs, &instr, &type, &size, &ea); > > for (i = 0; i < nr_wp_slots(); i++) { > bp[i] = __this_cpu_read(bp_per_reg[i]); > @@ -742,7 +587,7 @@ int hw_breakpoint_handler(struct die_args *args) > info[i] = counter_arch_bp(bp[i]); > info[i]->type &= ~HW_BRK_TYPE_EXTRANEOUS_IRQ; > > - if (check_constraints(regs, instr, ea, type, size, info[i])) { > + if (wp_check_constraints(regs, instr, ea, type, size, info[i])) { > if (!IS_ENABLED(CONFIG_PPC_8xx) && > ppc_inst_equal(instr, ppc_inst(0))) { > handler_error(bp[i], info[i]); > diff --git a/arch/powerpc/kernel/hw_breakpoint_constraints.c b/arch/powerpc/kernel/hw_breakpoint_constraints.c > new file mode 100644 > index 000000000000..867ee4aa026a > --- /dev/null > +++ b/arch/powerpc/kernel/hw_breakpoint_constraints.c > @@ -0,0 +1,162 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +#include > +#include > +#include > +#include > +#include > +#include > + > +static bool dar_in_user_range(unsigned long dar, struct arch_hw_breakpoint *info) > +{ > + return ((info->address <= dar) && (dar - info->address < info->len)); > +} > + > +static bool ea_user_range_overlaps(unsigned long ea, int size, > + struct arch_hw_breakpoint *info) > +{ > + return ((ea < info->address + info->len) && > + (ea + size > info->address)); > +} > + > +static bool dar_in_hw_range(unsigned long dar, struct arch_hw_breakpoint *info) > +{ > + unsigned long hw_start_addr, hw_end_addr; > + > + hw_start_addr = ALIGN_DOWN(info->address, HW_BREAKPOINT_SIZE); > + hw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE); > + > + return ((hw_start_addr <= dar) && (hw_end_addr > dar)); > +} > + > +static bool ea_hw_range_overlaps(unsigned long ea, int size, > + struct arch_hw_breakpoint *info) > +{ > + unsigned long hw_start_addr, hw_end_addr; > + unsigned long align_size = HW_BREAKPOINT_SIZE; > + > + /* > + * On p10 predecessors, quadword is handle differently then > + * other instructions. > + */ > + if (!cpu_has_feature(CPU_FTR_ARCH_31) && size == 16) > + align_size = HW_BREAKPOINT_SIZE_QUADWORD; > + > + hw_start_addr = ALIGN_DOWN(info->address, align_size); > + hw_end_addr = ALIGN(info->address + info->len, align_size); > + > + return ((ea < hw_end_addr) && (ea + size > hw_start_addr)); > +} > + > +/* > + * If hw has multiple DAWR registers, we also need to check all > + * dawrx constraint bits to confirm this is _really_ a valid event. > + * If type is UNKNOWN, but privilege level matches, consider it as > + * a positive match. > + */ > +static bool check_dawrx_constraints(struct pt_regs *regs, int type, > + struct arch_hw_breakpoint *info) > +{ > + if (OP_IS_LOAD(type) && !(info->type & HW_BRK_TYPE_READ)) > + return false; > + > + /* > + * The Cache Management instructions other than dcbz never > + * cause a match. i.e. if type is CACHEOP, the instruction > + * is dcbz, and dcbz is treated as Store. > + */ > + if ((OP_IS_STORE(type) || type == CACHEOP) && !(info->type & HW_BRK_TYPE_WRITE)) > + return false; > + > + if (is_kernel_addr(regs->nip) && !(info->type & HW_BRK_TYPE_KERNEL)) > + return false; > + > + if (user_mode(regs) && !(info->type & HW_BRK_TYPE_USER)) > + return false; > + > + return true; > +} > + > +/* > + * Return true if the event is valid wrt dawr configuration, > + * including extraneous exception. Otherwise return false. > + */ > +bool wp_check_constraints(struct pt_regs *regs, struct ppc_inst instr, > + unsigned long ea, int type, int size, > + struct arch_hw_breakpoint *info) > +{ > + bool in_user_range = dar_in_user_range(regs->dar, info); > + bool dawrx_constraints; > + > + /* > + * 8xx supports only one breakpoint and thus we can > + * unconditionally return true. > + */ > + if (IS_ENABLED(CONFIG_PPC_8xx)) { > + if (!in_user_range) > + info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ; > + return true; > + } > + > + if (unlikely(ppc_inst_equal(instr, ppc_inst(0)))) { > + if (cpu_has_feature(CPU_FTR_ARCH_31) && > + !dar_in_hw_range(regs->dar, info)) > + return false; > + > + return true; > + } > + > + dawrx_constraints = check_dawrx_constraints(regs, type, info); > + > + if (type == UNKNOWN) { > + if (cpu_has_feature(CPU_FTR_ARCH_31) && > + !dar_in_hw_range(regs->dar, info)) > + return false; > + > + return dawrx_constraints; > + } > + > + if (ea_user_range_overlaps(ea, size, info)) > + return dawrx_constraints; > + > + if (ea_hw_range_overlaps(ea, size, info)) { > + if (dawrx_constraints) { > + info->type |= HW_BRK_TYPE_EXTRANEOUS_IRQ; > + return true; > + } > + } > + return false; > +} > + > +static int cache_op_size(void) > +{ > +#ifdef __powerpc64__ > + return ppc64_caches.l1d.block_size; > +#else > + return L1_CACHE_BYTES; > +#endif > +} > + > +void wp_get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr, > + int *type, int *size, unsigned long *ea) > +{ > + struct instruction_op op; > + > + if (__get_user_instr_inatomic(*instr, (void __user *)regs->nip)) > + return; > + > + analyse_instr(&op, regs, *instr); > + *type = GETTYPE(op.type); > + *ea = op.ea; > +#ifdef __powerpc64__ > + if (!(regs->msr & MSR_64BIT)) > + *ea &= 0xffffffffUL; > +#endif > + > + *size = GETSIZE(op.type); > + if (*type == CACHEOP) { > + *size = cache_op_size(); > + *ea &= ~(*size - 1); > + } else if (*type == LOAD_VMX || *type == STORE_VMX) { > + *ea &= ~(*size - 1); > + } > +} >