mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
cpu: Support a target CPU having a variable page size
Support target CPUs having a page size which isn't knownn at compile time. To use this, the CPU implementation should: * define TARGET_PAGE_BITS_VARY * not define TARGET_PAGE_BITS * define TARGET_PAGE_BITS_MIN to the smallest value it might possibly want for TARGET_PAGE_BITS * call set_preferred_target_page_bits() in its realize function to indicate the actual preferred target page size for the CPU (and report any error from it) In CONFIG_USER_ONLY, the CPU implementation should continue to define TARGET_PAGE_BITS appropriately for the guest OS page size. Machines which want to take advantage of having the page size something larger than TARGET_PAGE_BITS_MIN must set the MachineClass minimum_page_bits field to a value which they guarantee will be no greater than the preferred page size for any CPU they create. Note that changing the target page size by setting minimum_page_bits is a migration compatibility break for that machine. For debugging purposes, attempts to use TARGET_PAGE_SIZE before it has been finally confirmed will assert. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
66ec9f4939
commit
20bccb82ff
5 changed files with 80 additions and 0 deletions
42
exec.c
42
exec.c
|
@ -93,6 +93,11 @@ static MemoryRegion io_mem_unassigned;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_PAGE_BITS_VARY
|
||||
int target_page_bits;
|
||||
bool target_page_bits_decided;
|
||||
#endif
|
||||
|
||||
struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
|
||||
/* current CPU in the current thread. It is only valid inside
|
||||
cpu_exec() */
|
||||
|
@ -102,8 +107,37 @@ __thread CPUState *current_cpu;
|
|||
2 = Adaptive rate instruction counting. */
|
||||
int use_icount;
|
||||
|
||||
bool set_preferred_target_page_bits(int bits)
|
||||
{
|
||||
/* The target page size is the lowest common denominator for all
|
||||
* the CPUs in the system, so we can only make it smaller, never
|
||||
* larger. And we can't make it smaller once we've committed to
|
||||
* a particular size.
|
||||
*/
|
||||
#ifdef TARGET_PAGE_BITS_VARY
|
||||
assert(bits >= TARGET_PAGE_BITS_MIN);
|
||||
if (target_page_bits == 0 || target_page_bits > bits) {
|
||||
if (target_page_bits_decided) {
|
||||
return false;
|
||||
}
|
||||
target_page_bits = bits;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
static void finalize_target_page_bits(void)
|
||||
{
|
||||
#ifdef TARGET_PAGE_BITS_VARY
|
||||
if (target_page_bits == 0) {
|
||||
target_page_bits = TARGET_PAGE_BITS_MIN;
|
||||
}
|
||||
target_page_bits_decided = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct PhysPageEntry PhysPageEntry;
|
||||
|
||||
struct PhysPageEntry {
|
||||
|
@ -2807,6 +2841,14 @@ void cpu_register_map_client(QEMUBH *bh)
|
|||
void cpu_exec_init_all(void)
|
||||
{
|
||||
qemu_mutex_init(&ram_list.mutex);
|
||||
/* The data structures we set up here depend on knowing the page size,
|
||||
* so no more changes can be made after this point.
|
||||
* In an ideal world, nothing we did before we had finished the
|
||||
* machine setup would care about the target page size, and we could
|
||||
* do this much later, rather than requiring board models to state
|
||||
* up front what their requirements are.
|
||||
*/
|
||||
finalize_target_page_bits();
|
||||
io_mem_init();
|
||||
memory_map_init();
|
||||
qemu_mutex_init(&map_client_list_lock);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue