|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 3/5] xen/ppc: Define minimal stub headers required for full build
On 9/5/23 10:52 AM, Jan Beulich wrote:
> On 01.09.2023 20:25, Shawn Anastasio wrote:
>> --- /dev/null
>> +++ b/xen/arch/ppc/include/asm/device.h
>> @@ -0,0 +1,53 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +#ifndef __ASM_PPC_DEVICE_H__
>> +#define __ASM_PPC_DEVICE_H__
>> +
>> +enum device_type
>> +{
>> + DEV_DT,
>> + DEV_PCI,
>> +};
>> +
>> +struct device {
>> + enum device_type type;
>> +#ifdef CONFIG_HAS_DEVICE_TREE
>> + struct dt_device_node *of_node; /* Used by drivers imported from Linux
>> */
>> +#endif
>> +};
>> +
>> +enum device_class
>> +{
>> + DEVICE_SERIAL,
>> + DEVICE_IOMMU,
>> + DEVICE_PCI_HOSTBRIDGE,
>> + /* Use for error */
>> + DEVICE_UNKNOWN,
>> +};
>> +
>> +struct device_desc {
>> + /* Device name */
>> + const char *name;
>> + /* Device class */
>> + enum device_class class;
>> + /* List of devices supported by this driver */
>> + const struct dt_device_match *dt_match;
>> + /*
>> + * Device initialization.
>> + *
>> + * -EAGAIN is used to indicate that device probing is deferred.
>> + */
>> + int (*init)(struct dt_device_node *dev, const void *data);
>> +};
>> +
>> +typedef struct device device_t;
>> +
>> +#define DT_DEVICE_START(_name, _namestr, _class) \
>
> Nit: Underscore-prefixed macro parameter names again.
>
Will fix.
>> --- a/xen/arch/ppc/include/asm/mm.h
>> +++ b/xen/arch/ppc/include/asm/mm.h
>> @@ -1,10 +1,25 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> #ifndef _ASM_PPC_MM_H
>> #define _ASM_PPC_MM_H
>>
>> +#include <public/xen.h>
>> +#include <xen/pdx.h>
>> +#include <xen/types.h>
>> +#include <asm/config.h>
>> #include <asm/page-bits.h>
>> +#include <asm/page.h>
>> +
>> +void setup_initial_pagetables(void);
>>
>> #define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)
>> #define paddr_to_pfn(pa) ((unsigned long)((pa) >> PAGE_SHIFT))
>> +#define paddr_to_pdx(pa) mfn_to_pdx(maddr_to_mfn(pa))
>> +#define gfn_to_gaddr(gfn) pfn_to_paddr(gfn_x(gfn))
>> +#define gaddr_to_gfn(ga) _gfn(paddr_to_pfn(ga))
>> +#define mfn_to_maddr(mfn) pfn_to_paddr(mfn_x(mfn))
>> +#define maddr_to_mfn(ma) _mfn(paddr_to_pfn(ma))
>> +#define vmap_to_mfn(va) maddr_to_mfn(virt_to_maddr((vaddr_t)va))
>> +#define vmap_to_page(va) mfn_to_page(vmap_to_mfn(va))
>>
>> #define virt_to_maddr(va) ((paddr_t)((vaddr_t)(va) & PADDR_MASK))
>> #define maddr_to_virt(pa) ((void *)((paddr_t)(pa) | XEN_VIRT_START))
>
> Is it intentional that the additions don't align, padding-wise, with the
> surrounding #define-s?
>
No -- good catch. I'll adjust the padding to line up properly.
>> @@ -13,6 +28,237 @@
>> #define __pa(x) (virt_to_maddr(x))
>> #define __va(x) (maddr_to_virt(x))
>>
>> -void setup_initial_pagetables(void);
>> +/* Convert between Xen-heap virtual addresses and machine frame numbers. */
>> +#define __virt_to_mfn(va) (virt_to_maddr(va) >> PAGE_SHIFT)
>> +#define __mfn_to_virt(mfn) (maddr_to_virt((paddr_t)(mfn) << PAGE_SHIFT))
>> +
>> +/* Convert between Xen-heap virtual addresses and page-info structures. */
>> +static inline struct page_info *virt_to_page(const void *v)
>> +{
>> + BUG_ON("unimplemented");
>> + return NULL;
>> +}
>> +
>> +/*
>> + * We define non-underscored wrappers for above conversion functions.
>> + * These are overriden in various source files while underscored version
>> + * remain intact.
>> + */
>> +#define virt_to_mfn(va) __virt_to_mfn(va)
>> +#define mfn_to_virt(mfn) __mfn_to_virt(mfn)
>
> Is the comment really applicable? The only non-arch-specific file still
> doing so is xenoprof.c, and I'm not sure you mean to support xenoprof
> on PPC. PPC-specific files would better be introduced in a type-safe way
> right from the beginning.
>
To be clear, you're suggesting that I define virt_to_mfn and mfn_to_virt
to operate on the type-safe mfn_t wrapper? When doing this,
xen/include/xen/domain_page.h:63 fails to build, since it seems to
assume that these macros do not use the type-safe mfn_t:
static inline void *map_domain_page_global(mfn_t mfn)
{
return mfn_to_virt(mfn_x(mfn));
}
If the comment is no longer accurate I can drop it, but there definitely
seems to be an assumption in the codebase that these macros operate on
raw unsigned longs rather than mfn_t.
>> +#define PG_shift(idx) (BITS_PER_LONG - (idx))
>> +#define PG_mask(x, idx) (x ## UL << PG_shift(idx))
>> +
>> +#define PGT_none PG_mask(0, 1) /* no special uses of this page
>> */
>> +#define PGT_writable_page PG_mask(1, 1) /* has writable mappings?
>> */
>> +#define PGT_type_mask PG_mask(1, 1) /* Bits 31 or 63.
>> */
>> +
>> + /* 2-bit count of uses of this frame as its current type. */
>> +#define PGT_count_mask PG_mask(3, 3)
>> +
>> +/* Cleared when the owning guest 'frees' this page. */
>> +#define _PGC_allocated PG_shift(1)
>> +#define PGC_allocated PG_mask(1, 1)
>> +/* Page is Xen heap? */
>> +#define _PGC_xen_heap PG_shift(2)
>> +#define PGC_xen_heap PG_mask(1, 2)
>> +/* Page is broken? */
>> +#define _PGC_broken PG_shift(7)
>> +#define PGC_broken PG_mask(1, 7)
>> + /* Mutually-exclusive page states: { inuse, offlining, offlined, free }. */
>> +#define PGC_state PG_mask(3, 9)
>> +#define PGC_state_inuse PG_mask(0, 9)
>> +#define PGC_state_offlining PG_mask(1, 9)
>> +#define PGC_state_offlined PG_mask(2, 9)
>> +#define PGC_state_free PG_mask(3, 9)
>> +#define page_state_is(pg, st) (((pg)->count_info&PGC_state) ==
>> PGC_state_##st)
>> +/* Page is not reference counted */
>> +#define _PGC_extra PG_shift(10)
>> +#define PGC_extra PG_mask(1, 10)
>> +
>> +/* Count of references to this frame. */
>> +#define PGC_count_width PG_shift(10)
>> +#define PGC_count_mask ((1UL<<PGC_count_width)-1)
>> +
>> +/*
>> + * Page needs to be scrubbed. Since this bit can only be set on a page that
>> is
>> + * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
>> + */
>> +#define _PGC_need_scrub _PGC_allocated
>> +#define PGC_need_scrub PGC_allocated
>> +
>> +#define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap)
>> +#define is_xen_heap_mfn(mfn) \
>> + (mfn_valid(mfn) && is_xen_heap_page(mfn_to_page(mfn)))
>> +
>> +#define is_xen_fixed_mfn(mfn) \
>> + ((mfn_to_maddr(mfn) >= virt_to_maddr(&_start)) && \
>> + (mfn_to_maddr(mfn) <= virt_to_maddr((vaddr_t)_end - 1)))
>
> Please use (or, preferred, do not use) & and cast consistently on _start
> and _end.
>
Will fix.
>> +#define page_get_owner(_p) (_p)->v.inuse.domain
>> +#define page_set_owner(_p,_d) ((_p)->v.inuse.domain = (_d))
>> +
>> +/* TODO: implement */
>> +#define mfn_valid(mfn) ({ (void) (mfn); 0; })
>> +
>> +#define domain_set_alloc_bitsize(d) ((void)(d))
>> +#define domain_clamp_alloc_bitsize(d, b) (b)
>> +
>> +#define PFN_ORDER(pfn_) ((pfn_)->v.free.order)
>> +
>> +struct page_info
>> +{
>> + /* Each frame can be threaded onto a doubly-linked list. */
>> + struct page_list_entry list;
>> +
>> + /* Reference count and various PGC_xxx flags and fields. */
>> + unsigned long count_info;
>> +
>> + /* Context-dependent fields follow... */
>> + union {
>> + /* Page is in use: ((count_info & PGC_count_mask) != 0). */
>> + struct {
>> + /* Type reference count and various PGT_xxx flags and fields. */
>> + unsigned long type_info;
>> + } inuse;
>> + /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
>> + union {
>> + struct {
>> + /*
>> + * Index of the first *possibly* unscrubbed page in the
>> buddy.
>> + * One more bit than maximum possible order to accommodate
>> + * INVALID_DIRTY_IDX.
>> + */
>> +#define INVALID_DIRTY_IDX ((1UL << (MAX_ORDER + 1)) - 1)
>> + unsigned long first_dirty:MAX_ORDER + 1;
>> +
>> + /* Do TLBs need flushing for safety before next page use? */
>> + bool need_tlbflush:1;
>> +
>> +#define BUDDY_NOT_SCRUBBING 0
>> +#define BUDDY_SCRUBBING 1
>> +#define BUDDY_SCRUB_ABORT 2
>> + unsigned long scrub_state:2;
>> + };
>> +
>> + unsigned long val;
>> + } free;
>> +
>> + } u;
>> +
>> + union {
>> + /* Page is in use, but not as a shadow. */
>> + struct {
>> + /* Owner of this page (zero if page is anonymous). */
>> + struct domain *domain;
>
> Since this is a pointer, NULL (instead of zero) would seem more appropriate
> in the comment.
>
Will update comment.
>> + } inuse;
>> +
>> + /* Page is on a free list. */
>> + struct {
>> + /* Order-size of the free chunk this page is the head of. */
>> + unsigned int order;
>> + } free;
>> +
>> + } v;
>> +
>> + union {
>> + /*
>> + * Timestamp from 'TLB clock', used to avoid extra safety flushes.
>> + * Only valid for: a) free pages, and b) pages with zero type count
>> + */
>> + u32 tlbflush_timestamp;
>> + };
>> + u64 pad;
>
> uint<N>_t please (or unsigned int/long).
>
Will use uint<N>_t.
>> --- /dev/null
>> +++ b/xen/arch/ppc/include/asm/monitor.h
>> @@ -0,0 +1,43 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/* Derived from xen/arch/arm/include/asm/monitor.h */
>> +#ifndef __ASM_PPC_MONITOR_H__
>> +#define __ASM_PPC_MONITOR_H__
>> +
>> +#include <public/domctl.h>
>> +#include <xen/errno.h>
>> +
>> +static inline
>> +void arch_monitor_allow_userspace(struct domain *d, bool allow_userspace)
>> +{
>> +}
>> +
>> +static inline
>> +int arch_monitor_domctl_op(struct domain *d, struct xen_domctl_monitor_op
>> *mop)
>> +{
>> + /* No arch-specific monitor ops on PPC. */
>> + return -EOPNOTSUPP;
>> +}
>> +
>> +int arch_monitor_domctl_event(struct domain *d,
>> + struct xen_domctl_monitor_op *mop);
>> +
>> +static inline
>> +int arch_monitor_init_domain(struct domain *d)
>> +{
>> + /* No arch-specific domain initialization on PPC. */
>> + return 0;
>> +}
>> +
>> +static inline
>> +void arch_monitor_cleanup_domain(struct domain *d)
>> +{
>> + /* No arch-specific domain cleanup on PPC. */
>> +}
>> +
>> +static inline uint32_t arch_monitor_get_capabilities(struct domain *d)
>> +{
>> + BUG_ON("unimplemented");
>> + return 0;
>> +}
>> +
>> +#endif /* __ASM_PPC_MONITOR_H__ */
>
>>From a formal perspective you'll need Tamas's ack for this file, so you
> may want to Cc him. (Also for vm_event.h, unless the generic solution
> there doesn't land first.)
>
My apologies, meant to CC him but forgot. Will do for next version of
series.
>> --- /dev/null
>> +++ b/xen/arch/ppc/include/asm/p2m.h
>> @@ -0,0 +1,105 @@
>> +#ifndef __ASM_PPC_P2M_H__
>> +#define __ASM_PPC_P2M_H__
>> +
>> +#include <asm/page-bits.h>
>> +
>> +#define paddr_bits PADDR_BITS
>> +
>> +/*
>> + * List of possible type for each page in the p2m entry.
>> + * The number of available bit per page in the pte for this purpose is 4
>> bits.
>> + * So it's possible to only have 16 fields. If we run out of value in the
>> + * future, it's possible to use higher value for pseudo-type and don't store
>> + * them in the p2m entry.
>> + */
>> +typedef enum {
>> + p2m_invalid = 0, /* Nothing mapped here */
>> + p2m_ram_rw, /* Normal read/write guest RAM */
>> + p2m_ram_ro, /* Read-only; writes are silently dropped */
>> + p2m_mmio_direct_dev,/* Read/write mapping of genuine Device MMIO area */
>> + p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area
>> non-cacheable */
>> + p2m_mmio_direct_c, /* Read/write mapping of genuine MMIO area
>> cacheable */
>
> Didn't you agree to drop at least what's clear Arm-specific?
>
Yes -- that was an oversight. Will fix.
>> --- a/xen/arch/ppc/include/asm/system.h
>> +++ b/xen/arch/ppc/include/asm/system.h
>> @@ -1,6 +1,228 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>> +/*
>> + * Copyright (C) IBM Corp. 2005
>> + * Copyright (C) Raptor Engineering LLC
>> + *
>> + * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
>> + * Shawn Anastasio <sanastasio@xxxxxxxxxxxxxxxxxxxxx>
>> + */
>> +
>> #ifndef _ASM_SYSTEM_H_
>> #define _ASM_SYSTEM_H_
>>
>> -#define smp_wmb() __asm__ __volatile__ ( "lwsync" : : : "memory" )
>> +#include <xen/lib.h>
>> +#include <asm/memory.h>
>> +#include <asm/time.h>
>> +#include <asm/processor.h>
>> +#include <asm/msr.h>
>> +
>> +#define xchg(ptr,x)
>> \
>> +({
>> \
>> + __typeof__(*(ptr)) _x_ = (x);
>> \
>
> Hard tabs look to have slipped in here.
>
Good eye. Will fix.
>> + (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr)));
>> \
>> +})
>> +
>> +#define build_xchg(fn, type, ldinsn, stinsn) \
>> +static inline unsigned long fn(volatile type *m, unsigned long val)
>> \
>> +{
>> \
>> + unsigned long dummy;
>> \
>> + asm volatile ( PPC_ATOMIC_ENTRY_BARRIER
>> \
>> + "1: " ldinsn " %0,0,%3\n"
>> \
>> + stinsn " %2,0,%3\n"
>> \
>> + "2: bne- 1b"
>> \
>> + PPC_ATOMIC_EXIT_BARRIER
>> \
>> + : "=&r" (dummy), "=m" (*m)
>> \
>> + : "r" (val), "r" (m)
>> \
>> + : "cc", "memory" );
>> \
>> + return dummy;
>> \
>> +}
>> +
>> +build_xchg(__xchg_u8, uint8_t, "lbarx", "stbcx.")
>> +build_xchg(__xchg_u16, uint16_t, "lharx", "sthcx.")
>> +build_xchg(__xchg_u32, uint32_t, "lwarx", "stwcx.")
>> +build_xchg(__xchg_u64, uint64_t, "ldarx", "stdcx.")
>> +
>> +#undef build_xchg
>> +
>> +/*
>> + * This function doesn't exist, so you'll get a linker error
>> + * if something tries to do an invalid xchg().
>> + */
>> +extern void __xchg_called_with_bad_pointer(void);
>> +
>> +static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
>> + int size)
>> +{
>> + switch (size) {
>
> Nit: Since the file looks like it wants to use Xen style:
>
> switch ( size )
> {
>
> please.
>
Will do.
>> + case 1:
>> + return __xchg_u8(ptr, x);
>> + case 2:
>> + return __xchg_u16(ptr, x);
>> + case 4:
>> + return __xchg_u32(ptr, x);
>> + case 8:
>> + return __xchg_u64(ptr, x);
>> + }
>> + __xchg_called_with_bad_pointer();
>> + return x;
>> +}
>> +
>> +
>> +static inline unsigned long __cmpxchg_u32(volatile int *p, int old, int new)
>> +{
>> + unsigned int prev;
>> +
>> + asm volatile ( PPC_ATOMIC_ENTRY_BARRIER
>> + "1: lwarx %0,0,%2\n"
>> + "cmpw 0,%0,%3\n"
>> + "bne- 2f\n "
>> + "stwcx. %4,0,%2\n"
>> + "bne- 1b\n"
>> + PPC_ATOMIC_EXIT_BARRIER "\n"
>> + "2:"
>> + : "=&r" (prev), "=m" (*p)
>> + : "r" (p), "r" (old), "r" (new), "m" (*p)
>> + : "cc", "memory" );
>> +
>> + return prev;
>> +}
>> +
>> +static inline unsigned long __cmpxchg_u64(volatile long *p, unsigned long
>> old,
>> + unsigned long new)
>> +{
>> + unsigned long prev;
>> +
>> + asm volatile ( PPC_ATOMIC_ENTRY_BARRIER
>> + "1: ldarx %0,0,%2\n"
>> + "cmpd 0,%0,%3\n"
>> + "bne- 2f\n"
>> + "stdcx. %4,0,%2\n"
>> + "bne- 1b"
>> + PPC_ATOMIC_EXIT_BARRIER "\n"
>> + "2:"
>> + : "=&r" (prev), "=m" (*p)
>> + : "r" (p), "r" (old), "r" (new), "m" (*p)
>> + : "cc", "memory" );
>> +
>> + return prev;
>> +}
>> +
>> +/* This function doesn't exist, so you'll get a linker error
>> + if something tries to do an invalid cmpxchg(). */
>> +extern void __cmpxchg_called_with_bad_pointer(void);
>> +
>> +static always_inline unsigned long __cmpxchg(
>> + volatile void *ptr,
>> + unsigned long old,
>> + unsigned long new,
>> + int size)
>> +{
>> + switch (size) {
>> + case 2:
>> + BUG_ON("unimplemented"); return 0; /* XXX implement __cmpxchg_u16 ?
>> */
>> + case 4:
>> + return __cmpxchg_u32(ptr, old, new);
>> + case 8:
>> + return __cmpxchg_u64(ptr, old, new);
>> + }
>> + __cmpxchg_called_with_bad_pointer();
>> + return old;
>> +}
>> +
>> +#define cmpxchg_user(ptr,o,n) cmpxchg(ptr,o,n)
>> +
>> +#define cmpxchg(ptr,o,n) \
>> + ({ \
>> + __typeof__(*(ptr)) _o_ = (o); \
>> + __typeof__(*(ptr)) _n_ = (n); \
>> + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
>> + (unsigned long)_n_, sizeof(*(ptr))); \
>
> Not: Style (multiple previously mentioned issues).
>
Will clean up.
>> + })
>> +
>> +
>> +/*
>> + * Memory barrier.
>> + * The sync instruction guarantees that all memory accesses initiated
>> + * by this processor have been performed (with respect to all other
>> + * mechanisms that access memory). The eieio instruction is a barrier
>> + * providing an ordering (separately) for (a) cacheable stores and (b)
>> + * loads and stores to non-cacheable memory (e.g. I/O devices).
>> + *
>> + * mb() prevents loads and stores being reordered across this point.
>> + * rmb() prevents loads being reordered across this point.
>> + * wmb() prevents stores being reordered across this point.
>> + * read_barrier_depends() prevents data-dependent loads being reordered
>> + * across this point (nop on PPC).
>> + *
>> + * We have to use the sync instructions for mb(), since lwsync doesn't
>> + * order loads with respect to previous stores. Lwsync is fine for
>> + * rmb(), though.
>> + * For wmb(), we use sync since wmb is used in drivers to order
>> + * stores to system memory with respect to writes to the device.
>> + * However, smp_wmb() can be a lighter-weight eieio barrier on
>> + * SMP since it is only used to order updates to system memory.
>> + */
>> +#define mb() __asm__ __volatile__ ("sync" : : : "memory")
>> +#define rmb() __asm__ __volatile__ ("lwsync" : : : "memory")
>> +#define wmb() __asm__ __volatile__ ("sync" : : : "memory")
>
> Nit: Missing blanks.
>
Will fix.
>> +#define read_barrier_depends() do { } while(0)
>> +
>> +#define set_mb(var, value) do { var = value; smp_mb(); } while (0)
>> +#define set_wmb(var, value) do { var = value; smp_wmb(); } while (0)
>> +
>> +#define smp_mb__before_atomic() smp_mb()
>> +#define smp_mb__after_atomic() smp_mb()
>> +
>> +#ifdef CONFIG_SMP
>> +#define smp_mb() mb()
>> +#define smp_rmb() rmb()
>> +#define smp_wmb() __asm__ __volatile__ ("lwsync" : : : "memory")
>> +#define smp_read_barrier_depends() read_barrier_depends()
>> +#else
>> +#define smp_mb() __asm__ __volatile__("": : :"memory")
>> +#define smp_rmb() __asm__ __volatile__("": : :"memory")
>> +#define smp_wmb() __asm__ __volatile__("": : :"memory")
>
> And more missing blanks (further below from here).
>
Will fix, along with removal of dead !CONFIG_SMP path.
>> +#define smp_read_barrier_depends() do { } while(0)
>> +#endif /* CONFIG_SMP */
>> +
>> +#define local_save_flags(flags) ((flags) = mfmsr())
>> +#define local_irq_restore(flags) do { \
>> + __asm__ __volatile__("": : :"memory"); \
>> + mtmsrd((flags)); \
>> +} while(0)
>> +
>> +static inline void local_irq_disable(void)
>> +{
>> + unsigned long msr;
>> + msr = mfmsr();
>> + mtmsrd(msr & ~MSR_EE);
>> + asm volatile ( "" : : : "memory" );
>
> That's simply barrier(), isn't it? Please avoid open-coding. (More
> further down.)
>
Good call. Will change all occurrences to barrier().
>> --- /dev/null
>> +++ b/xen/arch/ppc/include/asm/time.h
>> @@ -0,0 +1,21 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +#ifndef __ASM_PPC_TIME_H__
>> +#define __ASM_PPC_TIME_H__
>> +
>> +#include <xen/lib.h>
>> +#include <asm/processor.h>
>> +#include <asm/regs.h>
>> +
>> +struct vcpu;
>> +
>> +/* TODO: implement */
>> +static inline void force_update_vcpu_system_time(struct vcpu *v) {
>> BUG_ON("unimplemented"); }
>
> Nit: Too long line.
>
Will fix.
> Jan
Thanks,
Shawn
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |