Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-201703…
Browse files Browse the repository at this point in the history
…03' into staging

ppc patch queuye for 2017-03-03

This will probably be my last pull request before the hard freeze.  It
has some new work, but that has all been posted in draft before the
soft freeze, so I think it's reasonable to include in qemu-2.9.

This batch has:
    * A substantial amount of POWER9 work
        * Implements the legacy (hash) MMU for POWER9
	* Some more preliminaries for implementing the POWER9 radix
          MMU
	* POWER9 has_work
	* Basic POWER9 compatibility mode handling
	* Removal of some premature tests
    * Some cleanups and fixes to the existing MMU code to make the
      POWER9 work simpler
    * A bugfix for TCG multiply adds on power
    * Allow pseries guests to access PCIe extended config space

This also includes a code-motion not strictly in ppc code - moving
getrampagesize() from ppc code to exec.c.  This will make some future
VFIO improvements easier, Paolo said it was ok to merge via my tree.

# gpg: Signature made Fri 03 Mar 2017 03:20:36 GMT
# gpg:                using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <[email protected]>"
# gpg:                 aka "David Gibson (Red Hat) <[email protected]>"
# gpg:                 aka "David Gibson (ozlabs.org) <[email protected]>"
# gpg:                 aka "David Gibson (kernel.org) <[email protected]>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.9-20170303:
  target/ppc: rewrite f[n]m[add,sub] using float64_muladd
  spapr: Small cleanup of PPC MMU enums
  spapr_pci: Advertise access to PCIe extended config space
  target/ppc: Rework hash mmu page fault code and add defines for clarity
  target/ppc: Move no-execute and guarded page checking into new function
  target/ppc: Add execute permission checking to access authority check
  target/ppc: Add Instruction Authority Mask Register Check
  hw/ppc/spapr: Add POWER9 to pseries cpu models
  target/ppc/POWER9: Add cpu_has_work function for POWER9
  target/ppc/POWER9: Add POWER9 pa-features definition
  target/ppc/POWER9: Add POWER9 mmu fault handler
  target/ppc: Don't gen an SDR1 on POWER9 and rework register creation
  target/ppc: Add patb_entry to sPAPRMachineState
  target/ppc/POWER9: Add POWERPC_MMU_V3 bit
  powernv: Don't test POWER9 CPU yet
  exec, kvm, target-ppc: Move getrampagesize() to common code
  target/ppc: Add POWER9/ISAv3.00 to compat_table

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Mar 4, 2017
2 parents eeb61d4 + 992d7e9 commit 17783ac
Show file tree
Hide file tree
Showing 22 changed files with 735 additions and 495 deletions.
82 changes: 82 additions & 0 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "exec/memory.h"
#include "exec/ioport.h"
#include "sysemu/dma.h"
#include "sysemu/numa.h"
#include "exec/address-spaces.h"
#include "sysemu/xen-mapcache.h"
#include "trace-root.h"
Expand Down Expand Up @@ -1256,6 +1257,87 @@ void qemu_mutex_unlock_ramlist(void)
qemu_mutex_unlock(&ram_list.mutex);
}

#ifdef __linux__
/*
* FIXME TOCTTOU: this iterates over memory backends' mem-path, which
* may or may not name the same files / on the same filesystem now as
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
static int find_max_supported_pagesize(Object *obj, void *opaque)
{
char *mem_path;
long *hpsize_min = opaque;

if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
mem_path = object_property_get_str(obj, "mem-path", NULL);
if (mem_path) {
long hpsize = qemu_mempath_getpagesize(mem_path);
if (hpsize < *hpsize_min) {
*hpsize_min = hpsize;
}
} else {
*hpsize_min = getpagesize();
}
}

return 0;
}

long qemu_getrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
Object *memdev_root;

if (mem_path) {
mainrampagesize = qemu_mempath_getpagesize(mem_path);
} else {
mainrampagesize = getpagesize();
}

/* it's possible we have memory-backend objects with
* hugepage-backed RAM. these may get mapped into system
* address space via -numa parameters or memory hotplug
* hooks. we want to take these into account, but we
* also want to make sure these supported hugepage
* sizes are applicable across the entire range of memory
* we may boot from, so we take the min across all
* backends, and assume normal pages in cases where a
* backend isn't backed by hugepages.
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
return mainrampagesize;
}

/* If NUMA is disabled or the NUMA nodes are not backed with a
* memory-backend, then there is at least one node using "normal" RAM,
* so if its page size is smaller we have got to report that size instead.
*/
if (hpsize > mainrampagesize &&
(nb_numa_nodes == 0 || numa_info[0].node_memdev == NULL)) {
static bool warned;
if (!warned) {
error_report("Huge page support disabled (n/a for main memory).");
warned = true;
}
return mainrampagesize;
}

return hpsize;
}
#else
long qemu_getrampagesize(void)
{
return getpagesize();
}
#endif

#ifdef __linux__
static int64_t get_file_size(int fd)
{
Expand Down
55 changes: 50 additions & 5 deletions hw/ppc/spapr.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,20 +390,36 @@ static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset)
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
/* Currently we don't advertise any of the "new" ISAv3.00 functionality */
uint8_t pa_features_300[] = { 64, 0,
0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24 - 29 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 35 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 41 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 - 47 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 - 53 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 54 - 59 */
0x00, 0x00, 0x00, 0x00 }; /* 60 - 63 */

uint8_t *pa_features;
size_t pa_size;

switch (env->mmu_model) {
case POWERPC_MMU_2_06:
case POWERPC_MMU_2_06a:
switch (POWERPC_MMU_VER(env->mmu_model)) {
case POWERPC_MMU_VER_2_06:
pa_features = pa_features_206;
pa_size = sizeof(pa_features_206);
break;
case POWERPC_MMU_2_07:
case POWERPC_MMU_2_07a:
case POWERPC_MMU_VER_2_07:
pa_features = pa_features_207;
pa_size = sizeof(pa_features_207);
break;
case POWERPC_MMU_VER_3_00:
pa_features = pa_features_300;
pa_size = sizeof(pa_features_300);
break;
default:
return;
}
Expand Down Expand Up @@ -1055,6 +1071,13 @@ static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp,
}
}

static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp);

return spapr->patb_entry;
}

#define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2))
#define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID)
#define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY)
Expand Down Expand Up @@ -1234,6 +1257,8 @@ static void ppc_spapr_reset(void)
/* Check for unknown sysbus devices */
foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);

spapr->patb_entry = 0;

/* Allocate and/or reset the hash page table */
spapr_reallocate_hpt(spapr,
spapr_hpt_shift_for_ramsize(machine->maxram_size),
Expand Down Expand Up @@ -1427,6 +1452,24 @@ static const VMStateDescription vmstate_spapr_ov5_cas = {
},
};

static bool spapr_patb_entry_needed(void *opaque)
{
sPAPRMachineState *spapr = opaque;

return !!spapr->patb_entry;
}

static const VMStateDescription vmstate_spapr_patb_entry = {
.name = "spapr_patb_entry",
.version_id = 1,
.minimum_version_id = 1,
.needed = spapr_patb_entry_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(patb_entry, sPAPRMachineState),
VMSTATE_END_OF_LIST()
},
};

static const VMStateDescription vmstate_spapr = {
.name = "spapr",
.version_id = 3,
Expand All @@ -1444,6 +1487,7 @@ static const VMStateDescription vmstate_spapr = {
},
.subsections = (const VMStateDescription*[]) {
&vmstate_spapr_ov5_cas,
&vmstate_spapr_patb_entry,
NULL
}
};
Expand Down Expand Up @@ -3049,6 +3093,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
vhc->map_hptes = spapr_map_hptes;
vhc->unmap_hptes = spapr_unmap_hptes;
vhc->store_hpte = spapr_store_hpte;
vhc->get_patbe = spapr_get_patbe;
xic->ics_get = spapr_ics_get;
xic->ics_resend = spapr_ics_resend;
xic->icp_get = spapr_icp_get;
Expand Down
3 changes: 3 additions & 0 deletions hw/ppc/spapr_cpu_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ static const char *spapr_core_models[] = {

/* POWER8NVL */
"POWER8NVL_v1.0",

/* POWER9 */
"POWER9_v1.0",
};

void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
Expand Down
4 changes: 4 additions & 0 deletions hw/ppc/spapr_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,10 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
_FDT(fdt_setprop(fdt, offset, "assigned-addresses",
(uint8_t *)rp.assigned, rp.assigned_len));

if (pci_is_express(dev)) {
_FDT(fdt_setprop_cell(fdt, offset, "ibm,pci-config-space-type", 0x1));
}

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions include/exec/ram_addr.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset)
return (char *)block->host + offset;
}

long qemu_getrampagesize(void);
ram_addr_t last_ram_offset(void);
RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr,
bool share, const char *mem_path,
Expand Down
1 change: 1 addition & 0 deletions include/hw/ppc/spapr.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct sPAPRMachineState {

void *htab;
uint32_t htab_shift;
uint64_t patb_entry; /* Process tbl registed in H_REGISTER_PROCESS_TABLE */
hwaddr rma_size;
int vrma_adjust;
ssize_t rtas_size;
Expand Down
2 changes: 2 additions & 0 deletions include/qemu/mmap-alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

size_t qemu_fd_getpagesize(int fd);

size_t qemu_mempath_getpagesize(const char *mem_path);

void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared);

void qemu_ram_munmap(void *ptr, size_t size);
Expand Down
2 changes: 1 addition & 1 deletion target/ppc/Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ obj-y += cpu.o
obj-y += translate.o
ifeq ($(CONFIG_SOFTMMU),y)
obj-y += machine.o mmu_helper.o mmu-hash32.o monitor.o arch_dump.o
obj-$(TARGET_PPC64) += mmu-hash64.o compat.o
obj-$(TARGET_PPC64) += mmu-hash64.o mmu-book3s-v3.o compat.o
endif
obj-$(CONFIG_KVM) += kvm.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
Expand Down
16 changes: 11 additions & 5 deletions target/ppc/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,29 +39,35 @@ static const CompatInfo compat_table[] = {
*/
{ /* POWER6, ISA2.05 */
.pvr = CPU_POWERPC_LOGICAL_2_05,
.pcr = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05
| PCR_TM_DIS | PCR_VSX_DIS,
.pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
PCR_COMPAT_2_05 | PCR_TM_DIS | PCR_VSX_DIS,
.pcr_level = PCR_COMPAT_2_05,
.max_threads = 2,
},
{ /* POWER7, ISA2.06 */
.pvr = CPU_POWERPC_LOGICAL_2_06,
.pcr = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
.pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
.pcr_level = PCR_COMPAT_2_06,
.max_threads = 4,
},
{
.pvr = CPU_POWERPC_LOGICAL_2_06_PLUS,
.pcr = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
.pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_TM_DIS,
.pcr_level = PCR_COMPAT_2_06,
.max_threads = 4,
},
{ /* POWER8, ISA2.07 */
.pvr = CPU_POWERPC_LOGICAL_2_07,
.pcr = PCR_COMPAT_2_07,
.pcr = PCR_COMPAT_3_00 | PCR_COMPAT_2_07,
.pcr_level = PCR_COMPAT_2_07,
.max_threads = 8,
},
{ /* POWER9, ISA3.00 */
.pvr = CPU_POWERPC_LOGICAL_3_00,
.pcr = PCR_COMPAT_3_00,
.pcr_level = PCR_COMPAT_3_00,
.max_threads = 4,
},
};

static const CompatInfo *compat_by_pvr(uint32_t pvr)
Expand Down
16 changes: 9 additions & 7 deletions target/ppc/cpu-qom.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ enum powerpc_mmu_t {
#define POWERPC_MMU_1TSEG 0x00020000
#define POWERPC_MMU_AMR 0x00040000
#define POWERPC_MMU_64K 0x00080000
#define POWERPC_MMU_V3 0x00100000 /* ISA V3.00 MMU Support */
/* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
/* Architecture 2.03 and later (has LPCR) */
Expand All @@ -79,21 +80,22 @@ enum powerpc_mmu_t {
POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
| POWERPC_MMU_64K
| POWERPC_MMU_AMR | 0x00000003,
/* Architecture 2.06 "degraded" (no 1T segments) */
POWERPC_MMU_2_06a = POWERPC_MMU_64 | POWERPC_MMU_AMR
| 0x00000003,
/* Architecture 2.07 variant */
POWERPC_MMU_2_07 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
| POWERPC_MMU_64K
| POWERPC_MMU_AMR | 0x00000004,
/* Architecture 2.07 "degraded" (no 1T segments) */
POWERPC_MMU_2_07a = POWERPC_MMU_64 | POWERPC_MMU_AMR
| 0x00000004,
/* Architecture 3.00 variant */
POWERPC_MMU_3_00 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
| POWERPC_MMU_64K
| POWERPC_MMU_AMR | 0x00000005,
| POWERPC_MMU_AMR | POWERPC_MMU_V3
| 0x00000005,
};
#define POWERPC_MMU_VER(x) ((x) & (POWERPC_MMU_64 | 0xFFFF))
#define POWERPC_MMU_VER_64B POWERPC_MMU_VER(POWERPC_MMU_64B)
#define POWERPC_MMU_VER_2_03 POWERPC_MMU_VER(POWERPC_MMU_2_03)
#define POWERPC_MMU_VER_2_06 POWERPC_MMU_VER(POWERPC_MMU_2_06)
#define POWERPC_MMU_VER_2_07 POWERPC_MMU_VER(POWERPC_MMU_2_07)
#define POWERPC_MMU_VER_3_00 POWERPC_MMU_VER(POWERPC_MMU_3_00)

/*****************************************************************************/
/* Exception model */
Expand Down
17 changes: 17 additions & 0 deletions target/ppc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,22 @@ struct ppc_slb_t {
#endif
#endif

/* DSISR */
#define DSISR_NOPTE 0x40000000
/* Not permitted by access authority of encoded access authority */
#define DSISR_PROTFAULT 0x08000000
#define DSISR_ISSTORE 0x02000000
/* Not permitted by virtual page class key protection */
#define DSISR_AMR 0x00200000

/* SRR1 error code fields */

#define SRR1_NOPTE DSISR_NOPTE
/* Not permitted due to no-execute or guard bit set */
#define SRR1_NOEXEC_GUARD 0x10000000
#define SRR1_PROTFAULT DSISR_PROTFAULT
#define SRR1_IAMR DSISR_AMR

/* Facility Status and Control (FSCR) bits */
#define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */
#define FSCR_TAR (63 - 55) /* Target Address Register */
Expand Down Expand Up @@ -1216,6 +1232,7 @@ struct PPCVirtualHypervisorClass {
hwaddr ptex, int n);
void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex,
uint64_t pte0, uint64_t pte1);
uint64_t (*get_patbe)(PPCVirtualHypervisor *vhyp);
};

#define TYPE_PPC_VIRTUAL_HYPERVISOR "ppc-virtual-hypervisor"
Expand Down
Loading

0 comments on commit 17783ac

Please sign in to comment.