Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging

Patch queue for ppc - 2014-09-08

Alexander Graf (11):
      PPC: KVM: Fix g3beige and mac99 when HV is loaded
      PPC: mac99: Move NVRAM to page boundary when necessary
      KVM: Add helper to run KVM_CHECK_EXTENSION on vm fd
      PPC: KVM: Use vm check_extension for pv hcall
      PPC: mac99: Fix core99 timer frequency
      PPC: mac_nvram: Remove unused functions
      PPC: mac_nvram: Allow 2 and 4 byte accesses
      PPC: mac_nvram: Split NVRAM into OF and OSX parts
      PPC: Mac: Move tbfreq into local variable
      PPC: Cuda: Use cuda timer to expose tbfreq to guest
      PPC: Fix default config ordering and add eTSEC for ppc64

Alexey Kardashevskiy (7):
      spapr: Move DT memory node rendering to a helper
      spapr: Use DT memory node rendering helper for other nodes
      spapr: Refactor spapr_populate_memory() to allow memoryless nodes
      spapr: Split memory nodes to power-of-two blocks
      spapr: Add a helper for node0_size calculation
      spapr: Fix ibm, associativity for memory nodes
      spapr_pci: Fix config space corruption

Anton Blanchard (2):
      spapr-vlan: Don't touch last entry in buffer list
      hypervisor property clashes with hypervisor node

Benjamin Herrenschmidt (2):
      loader: Add load_image_size() to replace load_image()
      spapr: Locate RTAS and device-tree based on real RMA

Bharat Bhushan (4):
      ppc: debug stub: Get trap instruction opcode from KVM
      ppc: synchronize excp_vectors for injecting exception
      ppc: Add software breakpoint support
      ppc: Add hw breakpoint watchpoint support

Gonglei (1):
      spapr: fix possible memory leak

Greg Kurz (1):
      spapr_pci: map the MSI window in each PHB

Nikunj A Dadhania (3):
      ppc: spapr-rtas - implement os-term rtas call
      spapr: add uuid/host details to device tree
      ppc/spapr: Fix MAX_CPUS to 255

Peter Maydell (1):
      hw/ppc/spapr_hcall.c: Fix typo in function names

Tom Musta (20):
      linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame
      linux-user: Split PPC Trampoline Encoding from Register Save
      linux-user: Enable Signal Handlers on PPC64
      linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer
      linux-user: Implement do_setcontext for PPC64
      linux-user: Handle PPC64 ELFv2 Function Pointers
      target-ppc: Bug Fix: rlwinm
      target-ppc: Bug Fix: rlwnm
      target-ppc: Bug Fix: rlwimi
      target-ppc: Bug Fix: mullwo
      target-ppc: Bug Fix: mullw
      target-ppc: Bug Fix: mulldo OV Detection
      target-ppc: Bug Fix: srawi
      target-ppc: Bug Fix: srad
      target-ppc: Special Case of rlwimi Should Use Deposit
      target-ppc: Optimize rlwinm MB=0 ME=31
      target-ppc: Optimize rlwnm MB=0 ME=31
      target-ppc: Clean Up mullw
      target-ppc: Clean up mullwo
      target-ppc: Implement mulldo with TCG

# gpg: Signature made Mon 08 Sep 2014 11:51:15 BST using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found

* remotes/agraf/tags/signed-ppc-for-upstream: (52 commits)
  hypervisor property clashes with hypervisor node
  PPC: Fix default config ordering and add eTSEC for ppc64
  spapr_pci: map the MSI window in each PHB
  target-ppc: Implement mulldo with TCG
  target-ppc: Clean up mullwo
  target-ppc: Clean Up mullw
  target-ppc: Optimize rlwnm MB=0 ME=31
  target-ppc: Optimize rlwinm MB=0 ME=31
  target-ppc: Special Case of rlwimi Should Use Deposit
  spapr-vlan: Don't touch last entry in buffer list
  spapr_pci: Fix config space corruption
  PPC: Cuda: Use cuda timer to expose tbfreq to guest
  PPC: Mac: Move tbfreq into local variable
  PPC: mac_nvram: Split NVRAM into OF and OSX parts
  PPC: mac_nvram: Allow 2 and 4 byte accesses
  PPC: mac_nvram: Remove unused functions
  PPC: mac99: Fix core99 timer frequency
  PPC: KVM: Use vm check_extension for pv hcall
  KVM: Add helper to run KVM_CHECK_EXTENSION on vm fd
  target-ppc: Bug Fix: srad
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2014-09-08 12:02:07 +01:00
26 changed files with 933 additions and 304 deletions
+2 -2
View File
@@ -45,8 +45,8 @@ CONFIG_PREP=y
CONFIG_MAC=y
CONFIG_E500=y
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
CONFIG_ETSEC=y
CONFIG_LIBDECNUMBER=y
# For PReP
CONFIG_MC146818RTC=y
CONFIG_ETSEC=y
CONFIG_ISA_TESTDEV=y
CONFIG_LIBDECNUMBER=y
+2 -1
View File
@@ -46,6 +46,8 @@ CONFIG_PREP=y
CONFIG_MAC=y
CONFIG_E500=y
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
CONFIG_ETSEC=y
CONFIG_LIBDECNUMBER=y
# For pSeries
CONFIG_XICS=$(CONFIG_PSERIES)
CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
@@ -58,4 +60,3 @@ CONFIG_I82374=y
CONFIG_I8257=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
CONFIG_LIBDECNUMBER=y
+21
View File
@@ -89,6 +89,27 @@ int load_image(const char *filename, uint8_t *addr)
return size;
}
/* return the size or -1 if error */
ssize_t load_image_size(const char *filename, void *addr, size_t size)
{
int fd;
ssize_t actsize;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0) {
return -1;
}
actsize = read(fd, addr, size);
if (actsize < 0) {
close(fd);
return -1;
}
close(fd);
return actsize;
}
/* read()-like version */
ssize_t read_targphys(const char *name,
int fd, hwaddr dst_addr, size_t nbytes)
+20 -3
View File
@@ -123,13 +123,22 @@ static void cuda_update_irq(CUDAState *s)
}
}
static uint64_t get_tb(uint64_t freq)
{
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
freq, get_ticks_per_sec());
}
static unsigned int get_counter(CUDATimer *s)
{
int64_t d;
unsigned int counter;
uint64_t tb_diff;
/* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */
tb_diff = get_tb(s->frequency) - s->load_time;
d = (tb_diff * 0xBF401675E5DULL) / (s->frequency << 24);
d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->load_time,
CUDA_TIMER_FREQ, get_ticks_per_sec());
if (s->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (s->counter_value + 1)) {
@@ -147,7 +156,7 @@ static unsigned int get_counter(CUDATimer *s)
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
ti->load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ti->load_time = get_tb(s->frequency);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
@@ -688,6 +697,8 @@ static void cuda_realizefn(DeviceState *dev, Error **errp)
struct tm tm;
s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s);
s->timers[0].frequency = s->frequency;
s->timers[1].frequency = s->frequency;
qemu_get_timedate(&tm, 0);
s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
@@ -713,6 +724,11 @@ static void cuda_initfn(Object *obj)
DEVICE(obj), "adb.0");
}
static Property cuda_properties[] = {
DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0),
DEFINE_PROP_END_OF_LIST()
};
static void cuda_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -720,6 +736,7 @@ static void cuda_class_init(ObjectClass *oc, void *data)
dc->realize = cuda_realizefn;
dc->reset = cuda_reset;
dc->vmsd = &vmstate_cuda;
dc->props = cuda_properties;
}
static const TypeInfo cuda_type_info = {
+17 -2
View File
@@ -42,6 +42,7 @@ typedef struct MacIOState
void *dbdma;
MemoryRegion *pic_mem;
MemoryRegion *escc_mem;
uint64_t frequency;
} MacIOState;
#define OLDWORLD_MACIO(obj) \
@@ -243,13 +244,18 @@ static void timer_write(void *opaque, hwaddr addr, uint64_t value,
static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
{
uint32_t value = 0;
uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t kltime;
kltime = muldiv64(systime, 4194300, get_ticks_per_sec() * 4);
kltime = muldiv64(kltime, 18432000, 1048575);
switch (addr) {
case 0x38:
value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
value = kltime;
break;
case 0x3c:
value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 32;
value = kltime >> 32;
break;
}
@@ -346,12 +352,19 @@ static void macio_newworld_class_init(ObjectClass *oc, void *data)
pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
}
static Property macio_properties[] = {
DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0),
DEFINE_PROP_END_OF_LIST()
};
static void macio_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
k->vendor_id = PCI_VENDOR_ID_APPLE;
k->class_id = PCI_CLASS_OTHERS << 8;
dc->props = macio_properties;
}
static const TypeInfo macio_oldworld_type_info = {
@@ -398,6 +411,8 @@ void macio_init(PCIDevice *d,
macio_state->escc_mem = escc_mem;
/* Note: this code is strongly inspirated from the corresponding code
in PearPC */
qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
macio_state->frequency);
qdev_init_nofail(DEVICE(d));
}
+10 -3
View File
@@ -72,7 +72,14 @@ typedef uint64_t vlan_bd_t;
#define VLAN_RXQ_BD_OFF 0
#define VLAN_FILTER_BD_OFF 8
#define VLAN_RX_BDS_OFF 16
#define VLAN_MAX_BUFS ((SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
/*
* The final 8 bytes of the buffer list is a counter of frames dropped
* because there was not a buffer in the buffer list capable of holding
* the frame. We must avoid it, or the operating system will report garbage
* for this statistic.
*/
#define VLAN_RX_BDS_LEN (SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF - 8)
#define VLAN_MAX_BUFS (VLAN_RX_BDS_LEN / 8)
#define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
#define VIO_SPAPR_VLAN_DEVICE(obj) \
@@ -119,7 +126,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
do {
buf_ptr += 8;
if (buf_ptr >= SPAPR_TCE_PAGE_SIZE) {
if (buf_ptr >= (VLAN_RX_BDS_LEN + VLAN_RX_BDS_OFF)) {
buf_ptr = VLAN_RX_BDS_OFF;
}
@@ -397,7 +404,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
do {
dev->add_buf_ptr += 8;
if (dev->add_buf_ptr >= SPAPR_TCE_PAGE_SIZE) {
if (dev->add_buf_ptr >= (VLAN_RX_BDS_LEN + VLAN_RX_BDS_OFF)) {
dev->add_buf_ptr = VLAN_RX_BDS_OFF;
}
+44 -26
View File
@@ -26,6 +26,7 @@
#include "hw/nvram/openbios_firmware_abi.h"
#include "sysemu/sysemu.h"
#include "hw/ppc/mac.h"
#include <zlib.h>
/* debug NVR */
//#define DEBUG_NVR
@@ -39,29 +40,6 @@
#define DEF_SYSTEM_SIZE 0xc10
/* Direct access to NVRAM */
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr)
{
uint32_t ret;
if (addr < s->size) {
ret = s->data[addr];
} else {
ret = -1;
}
NVR_DPRINTF("read addr %04" PRIx32 " val %" PRIx8 "\n", addr, ret);
return ret;
}
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val)
{
NVR_DPRINTF("write addr %04" PRIx32 " val %" PRIx8 "\n", addr, val);
if (addr < s->size) {
s->data[addr] = val;
}
}
/* macio style NVRAM device */
static void macio_nvram_writeb(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
@@ -89,6 +67,10 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
static const MemoryRegionOps macio_nvram_ops = {
.read = macio_nvram_readb,
.write = macio_nvram_writeb,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
.impl.min_access_size = 1,
.impl.max_access_size = 1,
.endianness = DEVICE_BIG_ENDIAN,
};
@@ -156,15 +138,16 @@ static void macio_nvram_register_types(void)
}
/* Set up a system OpenBIOS NVRAM partition */
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
static void pmac_format_nvram_partition_of(MacIONVRAMState *nvr, int off,
int len)
{
unsigned int i;
uint32_t start = 0, end;
uint32_t start = off, end;
struct OpenBIOS_nvpart_v1 *part_header;
// OpenBIOS nvram variables
// Variable partition
part_header = (struct OpenBIOS_nvpart_v1 *)nvr->data;
part_header = (struct OpenBIOS_nvpart_v1 *)&nvr->data[start];
part_header->signature = OPENBIOS_PART_SYSTEM;
pstrcpy(part_header->name, sizeof(part_header->name), "system");
@@ -192,4 +175,39 @@ void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
OpenBIOS_finish_partition(part_header, end - start);
}
#define OSX_NVRAM_SIGNATURE (0x5A)
/* Set up a Mac OS X NVRAM partition */
static void pmac_format_nvram_partition_osx(MacIONVRAMState *nvr, int off,
int len)
{
uint32_t start = off;
struct OpenBIOS_nvpart_v1 *part_header;
unsigned char *data = &nvr->data[start];
/* empty partition */
part_header = (struct OpenBIOS_nvpart_v1 *)data;
part_header->signature = OSX_NVRAM_SIGNATURE;
pstrcpy(part_header->name, sizeof(part_header->name), "wwwwwwwwwwww");
OpenBIOS_finish_partition(part_header, len);
/* Generation */
stl_be_p(&data[20], 2);
/* Adler32 checksum */
stl_be_p(&data[16], adler32(0, &data[20], len - 20));
}
/* Set up NVRAM with OF and OSX partitions */
void pmac_format_nvram_partition(MacIONVRAMState *nvr, int len)
{
/*
* Mac OS X expects side "B" of the flash at the second half of NVRAM,
* so we use half of the chip for OF and the other half for a free OSX
* partition.
*/
pmac_format_nvram_partition_of(nvr, 0, len / 2);
pmac_format_nvram_partition_osx(nvr, len / 2, len / 2);
}
type_init(macio_nvram_register_types)
+2 -2
View File
@@ -57,6 +57,7 @@ typedef struct CUDATimer {
uint16_t counter_value;
int64_t load_time;
int64_t next_irq_time;
uint64_t frequency;
QEMUTimer *timer;
} CUDATimer;
@@ -97,6 +98,7 @@ typedef struct CUDAState {
CUDATimer timers[2];
uint32_t tick_offset;
uint64_t frequency;
uint8_t last_b;
uint8_t last_acr;
@@ -178,6 +180,4 @@ typedef struct MacIONVRAMState {
} MacIONVRAMState;
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr);
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val);
#endif /* !defined(__PPC_MAC_H__) */
+28 -4
View File
@@ -176,6 +176,8 @@ static void ppc_core99_init(MachineState *machine)
SysBusDevice *s;
DeviceState *dev;
int *token = g_new(int, 1);
hwaddr nvram_addr = 0xFFF04000;
uint64_t tbfreq;
linux_boot = (kernel_filename != NULL);
@@ -372,6 +374,14 @@ static void ppc_core99_init(MachineState *machine)
pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io());
machine_arch = ARCH_MAC99;
}
/* Timebase Frequency */
if (kvm_enabled()) {
tbfreq = kvmppc_get_tbfreq();
} else {
tbfreq = TBFREQ;
}
/* init basic PC hardware */
escc_mem = escc_init(0, pic[0x25], pic[0x24],
serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
@@ -385,6 +395,7 @@ static void ppc_core99_init(MachineState *machine)
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */
qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */
qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE DMA */
qdev_prop_set_uint64(dev, "frequency", tbfreq);
macio_init(macio, pic_mem, escc_bar);
/* We only emulate 2 out of 3 IDE controllers for now */
@@ -426,11 +437,18 @@ static void ppc_core99_init(MachineState *machine)
}
/* The NewWorld NVRAM is not located in the MacIO device */
#ifdef CONFIG_KVM
if (kvm_enabled() && getpagesize() > 4096) {
/* We can't combine read-write and read-only in a single page, so
move the NVRAM out of ROM again for KVM */
nvram_addr = 0xFFE00000;
}
#endif
dev = qdev_create(NULL, TYPE_MACIO_NVRAM);
qdev_prop_set_uint32(dev, "size", 0x2000);
qdev_prop_set_uint32(dev, "it_shift", 1);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xFFF04000);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, nvram_addr);
nvr = MACIO_NVRAM(dev);
pmac_format_nvram_partition(nvr, 0x2000);
/* No PCI init: the BIOS will do it */
@@ -461,28 +479,34 @@ static void ppc_core99_init(MachineState *machine)
#ifdef CONFIG_KVM
uint8_t *hypercall;
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
hypercall = g_malloc(16);
kvmppc_get_hypercall(env, hypercall, 16);
fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
#endif
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ);
}
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq);
/* Mac OS X requires a "known good" clock-frequency value; pass it one. */
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ);
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ);
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_NVRAM_ADDR, nvram_addr);
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
static int core99_kvm_type(const char *arg)
{
/* Always force PR KVM */
return 2;
}
static QEMUMachine core99_machine = {
.name = "mac99",
.desc = "Mac99 based PowerMAC",
.init = ppc_core99_init,
.max_cpus = MAX_CPUS,
.default_boot_order = "cd",
.kvm_type = core99_kvm_type,
};
static void core99_machine_init(void)
+17 -3
View File
@@ -103,6 +103,7 @@ static void ppc_heathrow_init(MachineState *machine)
uint16_t ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
void *fw_cfg;
uint64_t tbfreq;
linux_boot = (kernel_filename != NULL);
@@ -250,6 +251,13 @@ static void ppc_heathrow_init(MachineState *machine)
}
}
/* Timebase Frequency */
if (kvm_enabled()) {
tbfreq = kvmppc_get_tbfreq();
} else {
tbfreq = TBFREQ;
}
/* init basic PC hardware */
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
hw_error("Only 6xx bus is supported on heathrow machine\n");
@@ -278,6 +286,7 @@ static void ppc_heathrow_init(MachineState *machine)
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */
qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */
qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */
qdev_prop_set_uint64(dev, "frequency", tbfreq);
macio_init(macio, pic_mem, escc_bar);
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
@@ -330,15 +339,13 @@ static void ppc_heathrow_init(MachineState *machine)
#ifdef CONFIG_KVM
uint8_t *hypercall;
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
hypercall = g_malloc(16);
kvmppc_get_hypercall(env, hypercall, 16);
fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
#endif
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ);
}
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq);
/* Mac OS X requires a "known good" clock-frequency value; pass it one. */
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ);
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ);
@@ -346,6 +353,12 @@ static void ppc_heathrow_init(MachineState *machine)
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
static int heathrow_kvm_type(const char *arg)
{
/* Always force PR KVM */
return 2;
}
static QEMUMachine heathrow_machine = {
.name = "g3beige",
.desc = "Heathrow based PowerMAC",
@@ -355,6 +368,7 @@ static QEMUMachine heathrow_machine = {
.is_default = 1,
#endif
.default_boot_order = "cd", /* TOFIX "cad" when Mac floppy is implemented */
.kvm_type = heathrow_kvm_type,
};
static void heathrow_machine_init(void)
+120 -62
View File
@@ -71,6 +71,7 @@
*/
#define FDT_MAX_SIZE 0x40000
#define RTAS_MAX_SIZE 0x10000
#define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */
#define FW_MAX_SIZE 0x400000
#define FW_FILE_NAME "slof.bin"
#define FW_OVERHEAD 0x2800000
@@ -80,7 +81,7 @@
#define TIMEBASE_FREQ 512000000ULL
#define MAX_CPUS 256
#define MAX_CPUS 255
#define PHANDLE_XICP 0x00001111
@@ -283,6 +284,19 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
return (p - prop) * sizeof(uint32_t);
}
static hwaddr spapr_node0_size(void)
{
if (nb_numa_nodes) {
int i;
for (i = 0; i < nb_numa_nodes; ++i) {
if (numa_info[i].node_mem) {
return MIN(pow2floor(numa_info[i].node_mem), ram_size);
}
}
}
return ram_size;
}
#define _FDT(exp) \
do { \
int ret = (exp); \
@@ -319,6 +333,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL);
unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0;
uint32_t cpus_per_socket = sockets ? (smp_cpus / sockets) : 1;
char *buf;
add_str(hypertas, "hcall-pft");
add_str(hypertas, "hcall-term");
@@ -348,6 +363,29 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
_FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
_FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
/*
* Add info to guest to indentify which host is it being run on
* and what is the uuid of the guest
*/
if (kvmppc_get_host_model(&buf)) {
_FDT((fdt_property_string(fdt, "host-model", buf)));
g_free(buf);
}
if (kvmppc_get_host_serial(&buf)) {
_FDT((fdt_property_string(fdt, "host-serial", buf)));
g_free(buf);
}
buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
qemu_uuid[14], qemu_uuid[15]);
_FDT((fdt_property_string(fdt, "vm,uuid", buf)));
g_free(buf);
_FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
_FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
@@ -502,6 +540,15 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
_FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
/*
* According to PAPR, rtas ibm,os-term, does not gaurantee a return
* back to the guest cpu.
*
* While an additional ibm,extended-os-term property indicates that
* rtas call return will always occur. Set this property.
*/
_FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
_FDT((fdt_end_node(fdt)));
/* interrupt controller */
@@ -597,72 +644,75 @@ int spapr_h_cas_compose_response(target_ulong addr, target_ulong size)
return 0;
}
static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
static void spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
hwaddr size)
{
uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
cpu_to_be32(0x0), cpu_to_be32(0x0),
cpu_to_be32(0x0)};
uint32_t associativity[] = {
cpu_to_be32(0x4), /* length */
cpu_to_be32(0x0), cpu_to_be32(0x0),
cpu_to_be32(0x0), cpu_to_be32(nodeid)
};
char mem_name[32];
hwaddr node0_size, mem_start, node_size;
uint64_t mem_reg_property[2];
int i, off;
int off;
/* memory node(s) */
if (nb_numa_nodes > 1 && numa_info[0].node_mem < ram_size) {
node0_size = numa_info[0].node_mem;
} else {
node0_size = ram_size;
}
mem_reg_property[0] = cpu_to_be64(start);
mem_reg_property[1] = cpu_to_be64(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");
sprintf(mem_name, "memory@" TARGET_FMT_lx, 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))));
}
/* 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);
static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
{
hwaddr mem_start, node_size;
int i, nb_nodes = nb_numa_nodes;
NodeInfo *nodes = numa_info;
NodeInfo ramnode;
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))));
/* No NUMA nodes, assume there is just one node with whole RAM */
if (!nb_numa_nodes) {
nb_nodes = 1;
ramnode.node_mem = ram_size;
nodes = &ramnode;
}
/* 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);
for (i = 0, mem_start = 0; i < nb_nodes; ++i) {
if (!nodes[i].node_mem) {
continue;
}
if (mem_start >= ram_size) {
node_size = 0;
} else {
node_size = numa_info[i].node_mem;
node_size = nodes[i].node_mem;
if (node_size > ram_size - mem_start) {
node_size = ram_size - mem_start;
}
}
mem_reg_property[1] = cpu_to_be64(node_size);
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_size;
if (!mem_start) {
/* ppc_spapr_init() checks for rma_size <= node0_size already */
spapr_populate_memory_node(fdt, i, 0, spapr->rma_size);
mem_start += spapr->rma_size;
node_size -= spapr->rma_size;
}
for ( ; node_size; ) {
hwaddr sizetmp = pow2floor(node_size);
/* mem_start != 0 here */
if (ctzl(mem_start) < ctzl(sizetmp)) {
sizetmp = 1ULL << ctzl(mem_start);
}
spapr_populate_memory_node(fdt, i, mem_start, sizetmp);
node_size -= sizetmp;
mem_start += sizetmp;
}
}
return 0;
@@ -746,6 +796,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
g_free(bootlist);
g_free(fdt);
}
@@ -792,25 +843,38 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
/* Update the RMA size if necessary */
if (spapr->vrma_adjust) {
hwaddr node0_size = (nb_numa_nodes > 1) ?
numa_info[0].node_mem : ram_size;
spapr->rma_size = kvmppc_rma_size(node0_size, spapr->htab_shift);
spapr->rma_size = kvmppc_rma_size(spapr_node0_size(),
spapr->htab_shift);
}
}
static void ppc_spapr_reset(void)
{
PowerPCCPU *first_ppc_cpu;
uint32_t rtas_limit;
/* Reset the hash table & recalc the RMA */
spapr_reset_htab(spapr);
qemu_devices_reset();
/*
* 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(spapr->rma_size, RTAS_MAX_ADDR);
spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
/* Load the fdt */
spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
spapr->rtas_size);
/* Copy RTAS over */
cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
spapr->rtas_size);
/* Set up the entry state */
first_ppc_cpu = POWERPC_CPU(first_cpu);
first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
@@ -1227,10 +1291,10 @@ static void ppc_spapr_init(MachineState *machine)
MemoryRegion *rma_region;
void *rma = NULL;
hwaddr rma_alloc_size;
hwaddr node0_size = (nb_numa_nodes > 1) ? numa_info[0].node_mem : ram_size;
hwaddr node0_size = spapr_node0_size();
uint32_t initrd_base = 0;
long kernel_size = 0, initrd_size = 0;
long load_limit, rtas_limit, fw_size;
long load_limit, fw_size;
bool kernel_le = false;
char *filename;
@@ -1275,13 +1339,8 @@ static void ppc_spapr_init(MachineState *machine)
exit(1);
}
/* 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(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;
/* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
load_limit = MIN(spapr->rma_size, RTAS_MAX_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
@@ -1349,14 +1408,14 @@ static void ppc_spapr_init(MachineState *machine)
}
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);
if (spapr->rtas_size < 0) {
spapr->rtas_size = get_image_size(filename);
spapr->rtas_blob = g_malloc(spapr->rtas_size);
if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
exit(1);
}
if (spapr->rtas_size > RTAS_MAX_SIZE) {
hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
hw_error("RTAS too big ! 0x%zx bytes (max is 0x%x)\n",
spapr->rtas_size, RTAS_MAX_SIZE);
exit(1);
}
@@ -1378,7 +1437,6 @@ static void ppc_spapr_init(MachineState *machine)
spapr_create_nvram(spapr);
/* Set up PCI */
spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW);
spapr_pci_rtas_init();
phb = spapr_create_phb(spapr, 0);
+11 -11
View File
@@ -712,10 +712,10 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
return H_SUCCESS;
}
static target_ulong h_set_mode_resouce_le(PowerPCCPU *cpu,
target_ulong mflags,
target_ulong value1,
target_ulong value2)
static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
target_ulong mflags,
target_ulong value1,
target_ulong value2)
{
CPUState *cs;
@@ -743,10 +743,10 @@ static target_ulong h_set_mode_resouce_le(PowerPCCPU *cpu,
return H_UNSUPPORTED_FLAG;
}
static target_ulong h_set_mode_resouce_addr_trans_mode(PowerPCCPU *cpu,
target_ulong mflags,
target_ulong value1,
target_ulong value2)
static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
target_ulong mflags,
target_ulong value1,
target_ulong value2)
{
CPUState *cs;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
@@ -794,11 +794,11 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr,
switch (resource) {
case H_SET_MODE_RESOURCE_LE:
ret = h_set_mode_resouce_le(cpu, args[0], args[2], args[3]);
ret = h_set_mode_resource_le(cpu, args[0], args[2], args[3]);
break;
case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
ret = h_set_mode_resouce_addr_trans_mode(cpu, args[0],
args[2], args[3]);
ret = h_set_mode_resource_addr_trans_mode(cpu, args[0],
args[2], args[3]);
break;
}
+30 -31
View File
@@ -262,7 +262,6 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
unsigned int irq, max_irqs = 0, num = 0;
sPAPRPHBState *phb = NULL;
PCIDevice *pdev = NULL;
bool msix = false;
spapr_pci_msi *msi;
int *config_addr_key;
@@ -300,7 +299,12 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
}
xics_free(spapr->icp, msi->first_irq, msi->num);
spapr_msi_setmsg(pdev, 0, msix, 0, num);
if (msi_present(pdev)) {
spapr_msi_setmsg(pdev, 0, false, 0, num);
}
if (msix_present(pdev)) {
spapr_msi_setmsg(pdev, 0, true, 0, num);
}
g_hash_table_remove(phb->msi, &config_addr);
trace_spapr_pci_msi("Released MSIs", config_addr);
@@ -341,7 +345,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
}
/* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */
spapr_msi_setmsg(pdev, spapr->msi_win_addr, ret_intr_type == RTAS_TYPE_MSIX,
spapr_msi_setmsg(pdev, SPAPR_PCI_MSI_WINDOW, ret_intr_type == RTAS_TYPE_MSIX,
irq, req_num);
/* Add MSI device to cache */
@@ -465,34 +469,6 @@ static const MemoryRegionOps spapr_msi_ops = {
.endianness = DEVICE_LITTLE_ENDIAN
};
void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr)
{
uint64_t window_size = 4096;
/*
* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
* we need to allocate some memory to catch those writes coming
* from msi_notify()/msix_notify().
* As MSIMessage:addr is going to be the same and MSIMessage:data
* is going to be a VIRQ number, 4 bytes of the MSI MR will only
* be used.
*
* For KVM we want to ensure that this memory is a full page so that
* our memory slot is of page size granularity.
*/
#ifdef CONFIG_KVM
if (kvm_enabled()) {
window_size = getpagesize();
}
#endif
spapr->msi_win_addr = addr;
memory_region_init_io(&spapr->msiwindow, NULL, &spapr_msi_ops, spapr,
"msi", window_size);
memory_region_add_subregion(get_system_memory(), spapr->msi_win_addr,
&spapr->msiwindow);
}
/*
* PHB PCI device
*/
@@ -512,6 +488,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
char *namebuf;
int i;
PCIBus *bus;
uint64_t msi_window_size = 4096;
if (sphb->index != -1) {
hwaddr windows_base;
@@ -604,6 +581,28 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
address_space_init(&sphb->iommu_as, &sphb->iommu_root,
sphb->dtbusname);
/*
* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
* we need to allocate some memory to catch those writes coming
* from msi_notify()/msix_notify().
* As MSIMessage:addr is going to be the same and MSIMessage:data
* is going to be a VIRQ number, 4 bytes of the MSI MR will only
* be used.
*
* For KVM we want to ensure that this memory is a full page so that
* our memory slot is of page size granularity.
*/
#ifdef CONFIG_KVM
if (kvm_enabled()) {
msi_window_size = getpagesize();
}
#endif
memory_region_init_io(&sphb->msiwindow, NULL, &spapr_msi_ops, spapr,
"msi", msi_window_size);
memory_region_add_subregion(&sphb->iommu_root, SPAPR_PCI_MSI_WINDOW,
&sphb->msiwindow);
pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
+15
View File
@@ -277,6 +277,19 @@ static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
rtas_st(rets, 0, ret);
}
static void rtas_ibm_os_term(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
uint32_t nret, target_ulong rets)
{
target_ulong ret = 0;
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
rtas_st(rets, 0, ret);
}
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
@@ -404,6 +417,8 @@ static void core_rtas_register_types(void)
spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
"ibm,set-system-parameter",
rtas_ibm_set_system_parameter);
spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
rtas_ibm_os_term);
}
type_init(core_rtas_register_types)
+1
View File
@@ -13,6 +13,7 @@
*/
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
ssize_t load_image_size(const char *filename, void *addr, size_t size);
int load_image_targphys(const char *filename, hwaddr,
uint64_t max_sz);
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
+1 -1
View File
@@ -70,7 +70,7 @@ struct sPAPRPHBState {
MemoryRegion memspace, iospace;
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
MemoryRegion memwindow, iowindow;
MemoryRegion memwindow, iowindow, msiwindow;
uint32_t dma_liobn;
AddressSpace iommu_as;
+1 -1
View File
@@ -92,7 +92,7 @@ enum {
#define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05)
#define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06)
#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07)
/* OpenBIOS has FW_CFG_PPC_NVRAM_ADDR as +0x08 */
#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08)
#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09)
#define PPC_SERIAL_MM_BAUDBASE 399193
+3 -5
View File
@@ -13,8 +13,6 @@ struct sPAPRNVRAM;
typedef struct sPAPREnvironment {
struct VIOsPAPRBus *vio_bus;
QLIST_HEAD(, sPAPRPHBState) phbs;
hwaddr msi_win_addr;
MemoryRegion msiwindow;
struct sPAPRNVRAM *nvram;
XICSState *icp;
@@ -24,7 +22,8 @@ typedef struct sPAPREnvironment {
hwaddr rma_size;
int vrma_adjust;
hwaddr fdt_addr, rtas_addr;
long rtas_size;
ssize_t rtas_size;
void *rtas_blob;
void *fdt_skel;
target_ulong entry_point;
uint64_t rtc_offset;
@@ -382,9 +381,8 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
#define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D)
#define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E)
#define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F)
#define RTAS_IBM_EXTENDED_OS_TERM (RTAS_TOKEN_BASE + 0x20)
#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x21)
#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x20)
/* RTAS ibm,get-system-parameter token values */
#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
+2
View File
@@ -303,6 +303,8 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu);
int kvm_check_extension(KVMState *s, unsigned int extension);
int kvm_vm_check_extension(KVMState *s, unsigned int extension);
#define kvm_vm_enable_cap(s, capability, cap_flags, ...) \
({ \
struct kvm_enable_cap cap = { \
+13
View File
@@ -493,6 +493,19 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret;
}
int kvm_vm_check_extension(KVMState *s, unsigned int extension)
{
int ret;
ret = kvm_vm_ioctl(s, KVM_CHECK_EXTENSION, extension);
if (ret < 0) {
/* VM wide version not implemented, use global one instead */
ret = kvm_check_extension(s, extension);
}
return ret;
}
static int kvm_set_ioeventfd_mmio(int fd, hwaddr addr, uint32_t val,
bool assign, uint32_t size, bool datamatch)
{

Some files were not shown because too many files have changed in this diff Show More