2003-08-10 23:35:13 +02:00
|
|
|
/*
|
|
|
|
* common defines for all CPUs
|
2007-09-16 23:08:06 +02:00
|
|
|
*
|
2003-08-10 23:35:13 +02:00
|
|
|
* Copyright (c) 2003 Fabrice Bellard
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
2020-10-23 14:33:53 +02:00
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2003-08-10 23:35:13 +02:00
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2009-07-16 22:47:01 +02:00
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
2003-08-10 23:35:13 +02:00
|
|
|
*/
|
|
|
|
#ifndef CPU_DEFS_H
|
|
|
|
#define CPU_DEFS_H
|
|
|
|
|
2007-11-17 18:14:51 +01:00
|
|
|
#ifndef NEED_CPU_H
|
|
|
|
#error cpu.h included from common code
|
|
|
|
#endif
|
|
|
|
|
2016-03-15 15:36:13 +01:00
|
|
|
#include "qemu/host-utils.h"
|
cputlb: serialize tlb updates with env->tlb_lock
Currently we rely on atomic operations for cross-CPU invalidations.
There are two cases that these atomics miss: cross-CPU invalidations
can race with either (1) vCPU threads flushing their TLB, which
happens via memset, or (2) vCPUs calling tlb_reset_dirty on their TLB,
which updates .addr_write with a regular store. This results in
undefined behaviour, since we're mixing regular and atomic ops
on concurrent accesses.
Fix it by using tlb_lock, a per-vCPU lock. All updaters of tlb_table
and the corresponding victim cache now hold the lock.
The readers that do not hold tlb_lock must use atomic reads when
reading .addr_write, since this field can be updated by other threads;
the conversion to atomic reads is done in the next patch.
Note that an alternative fix would be to expand the use of atomic ops.
However, in the case of TLB flushes this would have a huge performance
impact, since (1) TLB flushes can happen very frequently and (2) we
currently use a full memory barrier to flush each TLB entry, and a TLB
has many entries. Instead, acquiring the lock is barely slower than a
full memory barrier since it is uncontended, and with a single lock
acquisition we can flush the entire TLB.
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <20181009174557.16125-6-cota@braap.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2018-10-09 19:45:56 +02:00
|
|
|
#include "qemu/thread.h"
|
2013-05-28 14:02:38 +02:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
2012-12-17 18:19:49 +01:00
|
|
|
#include "exec/hwaddr.h"
|
2013-05-28 14:02:38 +02:00
|
|
|
#endif
|
2015-04-26 17:49:24 +02:00
|
|
|
#include "exec/memattrs.h"
|
2019-07-09 17:20:52 +02:00
|
|
|
#include "hw/core/cpu.h"
|
2003-08-10 23:35:13 +02:00
|
|
|
|
2019-03-22 19:51:19 +01:00
|
|
|
#include "cpu-param.h"
|
|
|
|
|
2004-01-24 16:26:06 +01:00
|
|
|
#ifndef TARGET_LONG_BITS
|
2019-03-22 19:51:19 +01:00
|
|
|
# error TARGET_LONG_BITS must be defined in cpu-param.h
|
|
|
|
#endif
|
|
|
|
#ifndef TARGET_PHYS_ADDR_SPACE_BITS
|
|
|
|
# error TARGET_PHYS_ADDR_SPACE_BITS must be defined in cpu-param.h
|
|
|
|
#endif
|
|
|
|
#ifndef TARGET_VIRT_ADDR_SPACE_BITS
|
|
|
|
# error TARGET_VIRT_ADDR_SPACE_BITS must be defined in cpu-param.h
|
|
|
|
#endif
|
|
|
|
#ifndef TARGET_PAGE_BITS
|
|
|
|
# ifdef TARGET_PAGE_BITS_VARY
|
|
|
|
# ifndef TARGET_PAGE_BITS_MIN
|
|
|
|
# error TARGET_PAGE_BITS_MIN must be defined in cpu-param.h
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# error TARGET_PAGE_BITS must be defined in cpu-param.h
|
|
|
|
# endif
|
2004-01-24 16:26:06 +01:00
|
|
|
#endif
|
|
|
|
|
2023-03-03 03:58:00 +01:00
|
|
|
#include "exec/target_long.h"
|
2004-01-24 16:26:06 +01:00
|
|
|
|
2023-06-06 01:02:16 +02:00
|
|
|
#if defined(CONFIG_SOFTMMU) && defined(CONFIG_TCG)
|
2019-01-16 18:01:13 +01:00
|
|
|
#define CPU_TLB_DYN_MIN_BITS 6
|
|
|
|
#define CPU_TLB_DYN_DEFAULT_BITS 8
|
|
|
|
|
|
|
|
# if HOST_LONG_BITS == 32
|
|
|
|
/* Make sure we do not require a double-word shift for the TLB load */
|
|
|
|
# define CPU_TLB_DYN_MAX_BITS (32 - TARGET_PAGE_BITS)
|
|
|
|
# else /* HOST_LONG_BITS == 64 */
|
|
|
|
/*
|
|
|
|
* Assuming TARGET_PAGE_BITS==12, with 2**22 entries we can cover 2**(22+12) ==
|
|
|
|
* 2**34 == 16G of address space. This is roughly what one would expect a
|
|
|
|
* TLB to cover in a modern (as of 2018) x86_64 CPU. For instance, Intel
|
|
|
|
* Skylake's Level-2 STLB has 16 1G entries.
|
|
|
|
* Also, make sure we do not size the TLB past the guest's address space.
|
|
|
|
*/
|
osdep: Make MIN/MAX evaluate arguments only once
I'm not aware of any immediate bugs in qemu where a second runtime
evaluation of the arguments to MIN() or MAX() causes a problem, but
proactively preventing such abuse is easier than falling prey to an
unintended case down the road. At any rate, here's the conversation
that sparked the current patch:
https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg05718.html
Update the MIN/MAX macros to only evaluate their argument once at
runtime; this uses typeof(1 ? (a) : (b)) to ensure that we are
promoting the temporaries to the same type as the final comparison (we
have to trigger type promotion, as typeof(bitfield) won't compile; and
we can't use typeof((a) + (b)) or even typeof((a) + 0), as some of our
uses of MAX are on void* pointers where such addition is undefined).
However, we are unable to work around gcc refusing to compile ({}) in
a constant context (such as the array length of a static variable),
even when only used in the dead branch of a __builtin_choose_expr(),
so we have to provide a second macro pair MIN_CONST and MAX_CONST for
use when both arguments are known to be compile-time constants and
where the result must also be usable as a constant; this second form
evaluates arguments multiple times but that doesn't matter for
constants. By using a void expression as the expansion if a
non-constant is presented to this second form, we can enlist the
compiler to ensure the double evaluation is not attempted on
non-constants.
Alas, as both macros now rely on compiler intrinsics, they are no
longer usable in preprocessor #if conditions; those will just have to
be open-coded or the logic rewritten into #define or runtime 'if'
conditions (but where the compiler dead-code-elimination will probably
still apply).
I tested that both gcc 10.1.1 and clang 10.0.0 produce errors for all
forms of macro mis-use. As the errors can sometimes be cryptic, I'm
demonstrating the gcc output:
Use of MIN when MIN_CONST is needed:
In file included from /home/eblake/qemu/qemu-img.c:25:
/home/eblake/qemu/include/qemu/osdep.h:249:5: error: braced-group within expression allowed only inside a function
249 | ({ \
| ^
/home/eblake/qemu/qemu-img.c:92:12: note: in expansion of macro ‘MIN’
92 | char array[MIN(1, 2)] = "";
| ^~~
Use of MIN_CONST when MIN is needed:
/home/eblake/qemu/qemu-img.c: In function ‘is_allocated_sectors’:
/home/eblake/qemu/qemu-img.c:1225:15: error: void value not ignored as it ought to be
1225 | i = MIN_CONST(i, n);
| ^
Use of MIN in the preprocessor:
In file included from /home/eblake/qemu/accel/tcg/translate-all.c:20:
/home/eblake/qemu/accel/tcg/translate-all.c: In function ‘page_check_range’:
/home/eblake/qemu/include/qemu/osdep.h:249:6: error: token "{" is not valid in preprocessor expressions
249 | ({ \
| ^
Fix the resulting callsites that used #if or computed a compile-time
constant min or max to use the new macros. cpu-defs.h is interesting,
as CPU_TLB_DYN_MAX_BITS is sometimes used as a constant and sometimes
dynamic.
It may be worth improving glib's MIN/MAX definitions to be saner, but
that is a task for another day.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20200625162602.700741-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-06-25 18:26:02 +02:00
|
|
|
# ifdef TARGET_PAGE_BITS_VARY
|
|
|
|
# define CPU_TLB_DYN_MAX_BITS \
|
2019-01-16 18:01:13 +01:00
|
|
|
MIN(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS)
|
osdep: Make MIN/MAX evaluate arguments only once
I'm not aware of any immediate bugs in qemu where a second runtime
evaluation of the arguments to MIN() or MAX() causes a problem, but
proactively preventing such abuse is easier than falling prey to an
unintended case down the road. At any rate, here's the conversation
that sparked the current patch:
https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg05718.html
Update the MIN/MAX macros to only evaluate their argument once at
runtime; this uses typeof(1 ? (a) : (b)) to ensure that we are
promoting the temporaries to the same type as the final comparison (we
have to trigger type promotion, as typeof(bitfield) won't compile; and
we can't use typeof((a) + (b)) or even typeof((a) + 0), as some of our
uses of MAX are on void* pointers where such addition is undefined).
However, we are unable to work around gcc refusing to compile ({}) in
a constant context (such as the array length of a static variable),
even when only used in the dead branch of a __builtin_choose_expr(),
so we have to provide a second macro pair MIN_CONST and MAX_CONST for
use when both arguments are known to be compile-time constants and
where the result must also be usable as a constant; this second form
evaluates arguments multiple times but that doesn't matter for
constants. By using a void expression as the expansion if a
non-constant is presented to this second form, we can enlist the
compiler to ensure the double evaluation is not attempted on
non-constants.
Alas, as both macros now rely on compiler intrinsics, they are no
longer usable in preprocessor #if conditions; those will just have to
be open-coded or the logic rewritten into #define or runtime 'if'
conditions (but where the compiler dead-code-elimination will probably
still apply).
I tested that both gcc 10.1.1 and clang 10.0.0 produce errors for all
forms of macro mis-use. As the errors can sometimes be cryptic, I'm
demonstrating the gcc output:
Use of MIN when MIN_CONST is needed:
In file included from /home/eblake/qemu/qemu-img.c:25:
/home/eblake/qemu/include/qemu/osdep.h:249:5: error: braced-group within expression allowed only inside a function
249 | ({ \
| ^
/home/eblake/qemu/qemu-img.c:92:12: note: in expansion of macro ‘MIN’
92 | char array[MIN(1, 2)] = "";
| ^~~
Use of MIN_CONST when MIN is needed:
/home/eblake/qemu/qemu-img.c: In function ‘is_allocated_sectors’:
/home/eblake/qemu/qemu-img.c:1225:15: error: void value not ignored as it ought to be
1225 | i = MIN_CONST(i, n);
| ^
Use of MIN in the preprocessor:
In file included from /home/eblake/qemu/accel/tcg/translate-all.c:20:
/home/eblake/qemu/accel/tcg/translate-all.c: In function ‘page_check_range’:
/home/eblake/qemu/include/qemu/osdep.h:249:6: error: token "{" is not valid in preprocessor expressions
249 | ({ \
| ^
Fix the resulting callsites that used #if or computed a compile-time
constant min or max to use the new macros. cpu-defs.h is interesting,
as CPU_TLB_DYN_MAX_BITS is sometimes used as a constant and sometimes
dynamic.
It may be worth improving glib's MIN/MAX definitions to be saner, but
that is a task for another day.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20200625162602.700741-1-eblake@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-06-25 18:26:02 +02:00
|
|
|
# else
|
|
|
|
# define CPU_TLB_DYN_MAX_BITS \
|
|
|
|
MIN_CONST(22, TARGET_VIRT_ADDR_SPACE_BITS - TARGET_PAGE_BITS)
|
|
|
|
# endif
|
2019-01-16 18:01:13 +01:00
|
|
|
# endif
|
|
|
|
|
2023-06-06 01:02:16 +02:00
|
|
|
#endif /* CONFIG_SOFTMMU && CONFIG_TCG */
|
2023-02-17 21:11:36 +01:00
|
|
|
|
2003-08-10 23:35:13 +02:00
|
|
|
#endif
|