mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 08:13:54 -06:00
Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
* 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf: (35 commits) PPC: KVM: Fix BAT put PPC: e500: Only expose even TLB sizes in initial TLB ppc/pseries: Reset VPA registration on CPU reset pseries: Don't test for MSR_PR for hypercalls under KVM PPC: e500: calculate initrd_base like dt_base PPC: e500: increase DTC_LOAD_PAD device tree: simplify dumpdtb code fdt: move dumpdtb interpretation code to device_tree.c target-ppc: Remove unused power_mode field from cpu state pseries: Set hash table size based on RAM size pseries: Remove unnecessary locking from PAPR hash table hcalls ppc405_uc: Fix buffer overflow target-ppc: KVM: Fix some kernel version edge cases for kvmppc_reset_htab() pseries: Fix semantics of RTAS int-on, int-off and set-xive functions pseries: Rework implementation of TCE bypass pseries: Remove never used flags field from spapr vio devices pseries: Remove XICS irq type enum type pseries: Remove C bitfields from xics code pseries: Small cleanup to H_CEDE implementation pseries: Fix XICS reset ...
This commit is contained in:
commit
6b2f90fbbd
21 changed files with 576 additions and 437 deletions
343
hw/spapr.c
343
hw/spapr.c
|
@ -84,9 +84,11 @@
|
|||
|
||||
#define PHANDLE_XICP 0x00001111
|
||||
|
||||
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
|
||||
|
||||
sPAPREnvironment *spapr;
|
||||
|
||||
int spapr_allocate_irq(int hint, enum xics_irq_type type)
|
||||
int spapr_allocate_irq(int hint, bool lsi)
|
||||
{
|
||||
int irq;
|
||||
|
||||
|
@ -102,13 +104,13 @@ int spapr_allocate_irq(int hint, enum xics_irq_type type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
xics_set_irq_type(spapr->icp, irq, type);
|
||||
xics_set_irq_type(spapr->icp, irq, lsi);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
/* Allocate block of consequtive IRQs, returns a number of the first */
|
||||
int spapr_allocate_irq_block(int num, enum xics_irq_type type)
|
||||
int spapr_allocate_irq_block(int num, bool lsi)
|
||||
{
|
||||
int first = -1;
|
||||
int i;
|
||||
|
@ -116,7 +118,7 @@ int spapr_allocate_irq_block(int num, enum xics_irq_type type)
|
|||
for (i = 0; i < num; ++i) {
|
||||
int irq;
|
||||
|
||||
irq = spapr_allocate_irq(0, type);
|
||||
irq = spapr_allocate_irq(0, lsi);
|
||||
if (!irq) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -133,12 +135,13 @@ int spapr_allocate_irq_block(int num, enum xics_irq_type type)
|
|||
return first;
|
||||
}
|
||||
|
||||
static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
|
||||
static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
|
||||
{
|
||||
int ret = 0, offset;
|
||||
CPUPPCState *env;
|
||||
char cpu_model[32];
|
||||
int smt = kvmppc_smt_threads();
|
||||
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
|
||||
|
||||
assert(spapr->cpu_model);
|
||||
|
||||
|
@ -162,8 +165,16 @@ static int spapr_set_associativity(void *fdt, sPAPREnvironment *spapr)
|
|||
return offset;
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
|
||||
sizeof(associativity));
|
||||
if (nb_numa_nodes > 1) {
|
||||
ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
|
||||
sizeof(associativity));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = fdt_setprop(fdt, offset, "ibm,pft-size",
|
||||
pft_size_prop, sizeof(pft_size_prop));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -205,36 +216,6 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
|
|||
return (p - prop) * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
static void *spapr_create_fdt_skel(const char *cpu_model,
|
||||
target_phys_addr_t rma_size,
|
||||
target_phys_addr_t initrd_base,
|
||||
target_phys_addr_t initrd_size,
|
||||
target_phys_addr_t kernel_size,
|
||||
const char *boot_device,
|
||||
const char *kernel_cmdline,
|
||||
long hash_shift)
|
||||
{
|
||||
void *fdt;
|
||||
CPUPPCState *env;
|
||||
uint64_t mem_reg_property[2];
|
||||
uint32_t start_prop = cpu_to_be32(initrd_base);
|
||||
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
|
||||
uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
|
||||
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
|
||||
"\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
|
||||
char qemu_hypertas_prop[] = "hcall-memop1";
|
||||
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
|
||||
int i;
|
||||
char *modelname;
|
||||
int smt = kvmppc_smt_threads();
|
||||
unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
|
||||
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
|
||||
uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0)};
|
||||
char mem_name[32];
|
||||
target_phys_addr_t node0_size, mem_start;
|
||||
|
||||
#define _FDT(exp) \
|
||||
do { \
|
||||
int ret = (exp); \
|
||||
|
@ -245,6 +226,27 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
static void *spapr_create_fdt_skel(const char *cpu_model,
|
||||
target_phys_addr_t initrd_base,
|
||||
target_phys_addr_t initrd_size,
|
||||
target_phys_addr_t kernel_size,
|
||||
const char *boot_device,
|
||||
const char *kernel_cmdline)
|
||||
{
|
||||
void *fdt;
|
||||
CPUPPCState *env;
|
||||
uint32_t start_prop = cpu_to_be32(initrd_base);
|
||||
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
|
||||
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
|
||||
"\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk";
|
||||
char qemu_hypertas_prop[] = "hcall-memop1";
|
||||
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
|
||||
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
|
||||
char *modelname;
|
||||
int i, smt = kvmppc_smt_threads();
|
||||
unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
|
||||
|
||||
fdt = g_malloc0(FDT_MAX_SIZE);
|
||||
_FDT((fdt_create(fdt, FDT_MAX_SIZE)));
|
||||
|
||||
|
@ -288,55 +290,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
|
|||
|
||||
_FDT((fdt_end_node(fdt)));
|
||||
|
||||
/* memory node(s) */
|
||||
node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
|
||||
if (rma_size > node0_size) {
|
||||
rma_size = node0_size;
|
||||
}
|
||||
|
||||
/* RMA */
|
||||
mem_reg_property[0] = 0;
|
||||
mem_reg_property[1] = cpu_to_be64(rma_size);
|
||||
_FDT((fdt_begin_node(fdt, "memory@0")));
|
||||
_FDT((fdt_property_string(fdt, "device_type", "memory")));
|
||||
_FDT((fdt_property(fdt, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_property(fdt, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
_FDT((fdt_end_node(fdt)));
|
||||
|
||||
/* RAM: Node 0 */
|
||||
if (node0_size > rma_size) {
|
||||
mem_reg_property[0] = cpu_to_be64(rma_size);
|
||||
mem_reg_property[1] = cpu_to_be64(node0_size - rma_size);
|
||||
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, rma_size);
|
||||
_FDT((fdt_begin_node(fdt, mem_name)));
|
||||
_FDT((fdt_property_string(fdt, "device_type", "memory")));
|
||||
_FDT((fdt_property(fdt, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_property(fdt, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
_FDT((fdt_end_node(fdt)));
|
||||
}
|
||||
|
||||
/* RAM: Node 1 and beyond */
|
||||
mem_start = node0_size;
|
||||
for (i = 1; i < nb_numa_nodes; i++) {
|
||||
mem_reg_property[0] = cpu_to_be64(mem_start);
|
||||
mem_reg_property[1] = cpu_to_be64(node_mem[i]);
|
||||
associativity[3] = associativity[4] = cpu_to_be32(i);
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
|
||||
_FDT((fdt_begin_node(fdt, mem_name)));
|
||||
_FDT((fdt_property_string(fdt, "device_type", "memory")));
|
||||
_FDT((fdt_property(fdt, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_property(fdt, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
_FDT((fdt_end_node(fdt)));
|
||||
mem_start += node_mem[i];
|
||||
}
|
||||
|
||||
/* cpus */
|
||||
_FDT((fdt_begin_node(fdt, "cpus")));
|
||||
|
||||
|
@ -388,8 +341,6 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
|
|||
_FDT((fdt_property_cell(fdt, "timebase-frequency", tbfreq)));
|
||||
_FDT((fdt_property_cell(fdt, "clock-frequency", cpufreq)));
|
||||
_FDT((fdt_property_cell(fdt, "ibm,slb-size", env->slb_nr)));
|
||||
_FDT((fdt_property(fdt, "ibm,pft-size",
|
||||
pft_size_prop, sizeof(pft_size_prop))));
|
||||
_FDT((fdt_property_string(fdt, "status", "okay")));
|
||||
_FDT((fdt_property(fdt, "64-bit", NULL, 0)));
|
||||
|
||||
|
@ -488,6 +439,68 @@ static void *spapr_create_fdt_skel(const char *cpu_model,
|
|||
return fdt;
|
||||
}
|
||||
|
||||
static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
|
||||
{
|
||||
uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0)};
|
||||
char mem_name[32];
|
||||
target_phys_addr_t node0_size, mem_start;
|
||||
uint64_t mem_reg_property[2];
|
||||
int i, off;
|
||||
|
||||
/* memory node(s) */
|
||||
node0_size = (nb_numa_nodes > 1) ? node_mem[0] : ram_size;
|
||||
if (spapr->rma_size > node0_size) {
|
||||
spapr->rma_size = node0_size;
|
||||
}
|
||||
|
||||
/* RMA */
|
||||
mem_reg_property[0] = 0;
|
||||
mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
|
||||
off = fdt_add_subnode(fdt, 0, "memory@0");
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
_FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
|
||||
/* RAM: Node 0 */
|
||||
if (node0_size > spapr->rma_size) {
|
||||
mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
|
||||
mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
|
||||
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
|
||||
off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
_FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
}
|
||||
|
||||
/* RAM: Node 1 and beyond */
|
||||
mem_start = node0_size;
|
||||
for (i = 1; i < nb_numa_nodes; i++) {
|
||||
mem_reg_property[0] = cpu_to_be64(mem_start);
|
||||
mem_reg_property[1] = cpu_to_be64(node_mem[i]);
|
||||
associativity[3] = associativity[4] = cpu_to_be32(i);
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
|
||||
off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
_FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
mem_start += node_mem[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spapr_finalize_fdt(sPAPREnvironment *spapr,
|
||||
target_phys_addr_t fdt_addr,
|
||||
target_phys_addr_t rtas_addr,
|
||||
|
@ -502,6 +515,12 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
|
|||
/* open out the base tree into a temp buffer for the final tweaks */
|
||||
_FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
|
||||
|
||||
ret = spapr_populate_memory(spapr, fdt);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "couldn't setup memory nodes in fdt\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = spapr_populate_vdevice(spapr->vio_bus, fdt);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "couldn't setup vio devices in fdt\n");
|
||||
|
@ -524,11 +543,9 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
|
|||
}
|
||||
|
||||
/* Advertise NUMA via ibm,associativity */
|
||||
if (nb_numa_nodes > 1) {
|
||||
ret = spapr_set_associativity(fdt, spapr);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Couldn't set up NUMA device tree properties\n");
|
||||
}
|
||||
ret = spapr_fixup_cpu_dt(fdt, spapr);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Couldn't finalize CPU device tree properties\n");
|
||||
}
|
||||
|
||||
if (!spapr->has_graphics) {
|
||||
|
@ -555,15 +572,49 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
|||
|
||||
static void emulate_spapr_hypercall(CPUPPCState *env)
|
||||
{
|
||||
env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
|
||||
if (msr_pr) {
|
||||
hcall_dprintf("Hypercall made with MSR[PR]=1\n");
|
||||
env->gpr[3] = H_PRIVILEGE;
|
||||
} else {
|
||||
env->gpr[3] = spapr_hypercall(env, env->gpr[3], &env->gpr[4]);
|
||||
}
|
||||
}
|
||||
|
||||
static void spapr_reset(void *opaque)
|
||||
static void spapr_reset_htab(sPAPREnvironment *spapr)
|
||||
{
|
||||
sPAPREnvironment *spapr = (sPAPREnvironment *)opaque;
|
||||
long shift;
|
||||
|
||||
/* flush out the hash table */
|
||||
memset(spapr->htab, 0, spapr->htab_size);
|
||||
/* allocate hash page table. For now we always make this 16mb,
|
||||
* later we should probably make it scale to the size of guest
|
||||
* RAM */
|
||||
|
||||
shift = kvmppc_reset_htab(spapr->htab_shift);
|
||||
|
||||
if (shift > 0) {
|
||||
/* Kernel handles htab, we don't need to allocate one */
|
||||
spapr->htab_shift = shift;
|
||||
} else {
|
||||
if (!spapr->htab) {
|
||||
/* Allocate an htab if we don't yet have one */
|
||||
spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
|
||||
}
|
||||
|
||||
/* And clear it */
|
||||
memset(spapr->htab, 0, HTAB_SIZE(spapr));
|
||||
}
|
||||
|
||||
/* Update the RMA size if necessary */
|
||||
if (spapr->vrma_adjust) {
|
||||
spapr->rma_size = kvmppc_rma_size(ram_size, spapr->htab_shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc_spapr_reset(void)
|
||||
{
|
||||
/* Reset the hash table & recalc the RMA */
|
||||
spapr_reset_htab(spapr);
|
||||
|
||||
qemu_devices_reset();
|
||||
|
||||
/* Load the fdt */
|
||||
spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
|
||||
|
@ -580,8 +631,22 @@ static void spapr_reset(void *opaque)
|
|||
static void spapr_cpu_reset(void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
cpu_reset(CPU(cpu));
|
||||
|
||||
/* All CPUs start halted. CPU0 is unhalted from the machine level
|
||||
* reset code and the rest are explicitly started up by the guest
|
||||
* using an RTAS call */
|
||||
env->halted = 1;
|
||||
|
||||
env->spr[SPR_HIOR] = 0;
|
||||
|
||||
env->external_htab = spapr->htab;
|
||||
env->htab_base = -1;
|
||||
env->htab_mask = HTAB_SIZE(spapr) - 1;
|
||||
env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
|
||||
(spapr->htab_shift - 18);
|
||||
}
|
||||
|
||||
/* Returns whether we want to use VGA or not */
|
||||
|
@ -613,11 +678,10 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
|||
int i;
|
||||
MemoryRegion *sysmem = get_system_memory();
|
||||
MemoryRegion *ram = g_new(MemoryRegion, 1);
|
||||
target_phys_addr_t rma_alloc_size, rma_size;
|
||||
target_phys_addr_t rma_alloc_size;
|
||||
uint32_t initrd_base = 0;
|
||||
long kernel_size = 0, initrd_size = 0;
|
||||
long load_limit, rtas_limit, fw_size;
|
||||
long pteg_shift = 17;
|
||||
char *filename;
|
||||
|
||||
msi_supported = true;
|
||||
|
@ -634,20 +698,46 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
|||
hw_error("qemu: Unable to create RMA\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rma_alloc_size && (rma_alloc_size < ram_size)) {
|
||||
rma_size = rma_alloc_size;
|
||||
spapr->rma_size = rma_alloc_size;
|
||||
} else {
|
||||
rma_size = ram_size;
|
||||
spapr->rma_size = ram_size;
|
||||
|
||||
/* With KVM, we don't actually know whether KVM supports an
|
||||
* unbounded RMA (PR KVM) or is limited by the hash table size
|
||||
* (HV KVM using VRMA), so we always assume the latter
|
||||
*
|
||||
* In that case, we also limit the initial allocations for RTAS
|
||||
* etc... to 256M since we have no way to know what the VRMA size
|
||||
* is going to be as it depends on the size of the hash table
|
||||
* isn't determined yet.
|
||||
*/
|
||||
if (kvm_enabled()) {
|
||||
spapr->vrma_adjust = 1;
|
||||
spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
|
||||
}
|
||||
}
|
||||
|
||||
/* We place the device tree and RTAS just below either the top of the RMA,
|
||||
* or just below 2GB, whichever is lowere, so that it can be
|
||||
* processed with 32-bit real mode code if necessary */
|
||||
rtas_limit = MIN(rma_size, 0x80000000);
|
||||
rtas_limit = MIN(spapr->rma_size, 0x80000000);
|
||||
spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
|
||||
spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
|
||||
load_limit = spapr->fdt_addr - FW_OVERHEAD;
|
||||
|
||||
/* We aim for a hash table of size 1/128 the size of RAM. The
|
||||
* normal rule of thumb is 1/64 the size of RAM, but that's much
|
||||
* more than needed for the Linux guests we support. */
|
||||
spapr->htab_shift = 18; /* Minimum architected size */
|
||||
while (spapr->htab_shift <= 46) {
|
||||
if ((1ULL << (spapr->htab_shift + 7)) >= ram_size) {
|
||||
break;
|
||||
}
|
||||
spapr->htab_shift++;
|
||||
}
|
||||
|
||||
/* init CPUs */
|
||||
if (cpu_model == NULL) {
|
||||
cpu_model = kvm_enabled() ? "host" : "POWER7";
|
||||
|
@ -662,11 +752,16 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
|||
|
||||
/* Set time-base frequency to 512 MHz */
|
||||
cpu_ppc_tb_init(env, TIMEBASE_FREQ);
|
||||
qemu_register_reset(spapr_cpu_reset, cpu);
|
||||
|
||||
env->hreset_vector = 0x60;
|
||||
/* PAPR always has exception vectors in RAM not ROM */
|
||||
env->hreset_excp_prefix = 0;
|
||||
env->gpr[3] = env->cpu_index;
|
||||
|
||||
/* Tell KVM that we're in PAPR mode */
|
||||
if (kvm_enabled()) {
|
||||
kvmppc_set_papr(env);
|
||||
}
|
||||
|
||||
qemu_register_reset(spapr_cpu_reset, cpu);
|
||||
}
|
||||
|
||||
/* allocate RAM */
|
||||
|
@ -680,27 +775,6 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
|||
memory_region_add_subregion(sysmem, nonrma_base, ram);
|
||||
}
|
||||
|
||||
/* allocate hash page table. For now we always make this 16mb,
|
||||
* later we should probably make it scale to the size of guest
|
||||
* RAM */
|
||||
spapr->htab_size = 1ULL << (pteg_shift + 7);
|
||||
spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size);
|
||||
|
||||
for (env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
env->external_htab = spapr->htab;
|
||||
env->htab_base = -1;
|
||||
env->htab_mask = spapr->htab_size - 1;
|
||||
|
||||
/* Tell KVM that we're in PAPR mode */
|
||||
env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
|
||||
((pteg_shift + 7) - 18);
|
||||
env->spr[SPR_HIOR] = 0;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
kvmppc_set_papr(env);
|
||||
}
|
||||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
|
||||
spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
|
||||
rtas_limit - spapr->rtas_addr);
|
||||
|
@ -773,7 +847,7 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
|||
}
|
||||
}
|
||||
|
||||
if (rma_size < (MIN_RMA_SLOF << 20)) {
|
||||
if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
|
||||
fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
|
||||
"%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
|
||||
exit(1);
|
||||
|
@ -824,26 +898,19 @@ static void ppc_spapr_init(ram_addr_t ram_size,
|
|||
|
||||
spapr->entry_point = 0x100;
|
||||
|
||||
/* SLOF will startup the secondary CPUs using RTAS */
|
||||
for (env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
env->halted = 1;
|
||||
}
|
||||
|
||||
/* Prepare the device tree */
|
||||
spapr->fdt_skel = spapr_create_fdt_skel(cpu_model, rma_size,
|
||||
spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
|
||||
initrd_base, initrd_size,
|
||||
kernel_size,
|
||||
boot_device, kernel_cmdline,
|
||||
pteg_shift + 7);
|
||||
boot_device, kernel_cmdline);
|
||||
assert(spapr->fdt_skel != NULL);
|
||||
|
||||
qemu_register_reset(spapr_reset, spapr);
|
||||
}
|
||||
|
||||
static QEMUMachine spapr_machine = {
|
||||
.name = "pseries",
|
||||
.desc = "pSeries Logical Partition (PAPR compliant)",
|
||||
.init = ppc_spapr_init,
|
||||
.reset = ppc_spapr_reset,
|
||||
.max_cpus = MAX_CPUS,
|
||||
.no_parallel = 1,
|
||||
.use_scsi = 1,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue